ASP .NET - Construindo um Carrinho de Compras
Eu estou voltando a este assunto por que ele é recorrente e também para mostrar outra forma de construir um carrinho de compras com ASP .NET usando um enfoque mais orientado a objetos.
Neste enfoque eu não vou usar um banco de dados vou definir o modelo de classes e a partir dele criar um web site ASP .NET que mostra o funcionamento básico do carrinho de compras.
Criando o Projeto
Abra o Visual Web Developer 2010 Express Edition e crie um novo WebSite usando o modelo ASP .NET Empty Web Site com o nome CarrinhoComprasVB;
Vamos começar criando o modelo de classes da aplicação o qual irá conter as seguintes classes:
Vamos incluir uma nova classe na aplicação através do menu WebSite -> Add New Item e selecionando o template Class informando o nome Produto.vb;
A seguir inclua o código abaixo neste arquivo:
A classe produto ' Usada para simular o acesso aos dados dos produtos Public Class Produto #Region "Propriedades" Private _id As Integer Public Property Id() As Integer Get Return _id End Get Set(ByVal value As Integer) _id = value End Set End Property Private _preco As Decimal Public Property Preco() As Decimal Get Return _preco End Get Set(ByVal value As Decimal) _preco = value End Set End Property Private _descricao As String Public Property Descricao() As String Get Return _descricao End Get Set(ByVal value As String) _descricao = value End Set End Property #End Region Public Sub New(ByVal id As Integer) Me.Id = id If id = 1 Then Me.Preco = 1219.95 Me.Descricao = "NoteBook LG" ElseIf id = 2 Then Me.Preco = 1399.95 Me.Descricao = "IPad 2 16 GB" ElseIf id = 3 Then Me.Preco = 1815.55 Me.Descricao = "IPhone 4S" ElseIf id = 4 Then Me.Preco = 1025.10 Me.Descricao = "Pen Drive 16 Gb" End If End Sub End Class |
Nesta classe definimos as
seguintes propriedades:
E um construtor (Sub New) que inicia os membros da classe. |
Repita o procedimento e inclua uma nova classe ao projeto com o nome CarrinhoItem.vb a qual deverá ter o seguinte código:
Imports Microsoft.VisualBasic ' Classe CarrinhoItem ' Uma estrutura básica para tratar os dados dos itens Public Class CarrinhoItem Implements IEquatable(Of CarrinhoItem) #Region "Propriedades" ' Armazena a quantidade no carrinho Private _quantidade As Integer Public Property Quantidade() As Integer Get Return _quantidade End Get Set(ByVal value As Integer) _quantidade = value End Set End Property Private _produtoId As Integer Public Property ProdutoId() As Integer Get Return _produtoId End Get Set(ByVal value As Integer) ' Garante que o objeto Prod será recriado _prod = Nothing _produtoId = value End Set End Property Private _prod As Produto = Nothing Public ReadOnly Property Prod() As Produto Get ' Inicialização tardia (Lazy initialization) - o objeto não será criado até que seja requisitado If _prod Is Nothing Then _prod = New Produto(ProdutoId) End If Return _prod End Get End Property Public ReadOnly Property Descricao() As String Get Return Prod.Descricao End Get End Property Public ReadOnly Property PrecoUnitario() As Decimal Get Return Prod.Preco End Get End Property Public ReadOnly Property PrecoTotal() As Decimal Get Return PrecoUnitario * Quantidade End Get End Property #End Region ' Construtor CarrinhoItem somente precisa do codigo do produto Public Sub New(ByVal _produtoId As Integer) Me.ProdutoId = _produtoId End Sub ' Equals() - Necessario implementar a interface IEquatable ' Para testar se o item é igual ou não ao parametro ' Este método é chamado pelo método Contains() na classe List ' Usamos o método Contains() no método AddItem() da classe CarrinhoCompras Public Overloads Function Equals(ByVal item As CarrinhoItem) As Boolean Implements IEquatable(Of CarrinhoItem).Equals Return item.ProdutoId = Me.ProdutoId End Function End Class |
Agora inclua a última classe no projeto com o nome CarrinhoCompras.vb e o código abaixo:
Imports Microsoft.VisualBasic ' Classe carrinho de compras ' trata os itens que estão no carrinho e fornece métodos para manipulá-los Public Class CarrinhoCompras #Region "Propriedades" Private _items As List(Of CarrinhoItem) Public Property Items() As List(Of CarrinhoItem) Get Return _items End Get Private Set(ByVal value As List(Of CarrinhoItem)) _items = value End Set End Property #End Region #Region "Implementação Singleton" ' Variáveis Readonly podem ser definidas na inicialização ou construção Public Shared ReadOnly Instancia As CarrinhoCompras ' O construtor static é chamado tão logo a classe é carregada na memoria Shared Sub New() ' Se o carrinho não esta na sessão cria um novo carrinho e poe na memoria ' caso contrario pega o que esta na sessão If HttpContext.Current.Session("ASPNETCarrinhoCompras") Is Nothing Then Instancia = New CarrinhoCompras() Instancia.Items = New List(Of CarrinhoItem) HttpContext.Current.Session("ASPNETCarrinhoCompras") = Instancia Else Instancia = CType(HttpContext.Current.Session("ASPNETCarrinhoCompras"), CarrinhoCompras) End If End Sub ' Um construtor protected garante que um objeto não pode ser criado fora da classe Protected Sub New() End Sub #End Region #Region "Método modificação de Item" ' AddItem() - Inclui um item no carrinho Public Sub AddItem(ByVal produtoId As Integer) ' Cria um novo item para incluir no carrinho Dim novoItem = New CarrinhoItem(produtoId) ' Se o item já existe na lista de itens aumenta a quantidade ' senão inclui um novo item na lista If Items.Contains(novoItem) Then For Each item As CarrinhoItem In Items If item.Equals(novoItem) Then item.Quantidade += 1 Return End If Next Else novoItem.Quantidade = 1 Items.Add(novoItem) End If End Sub ' setItemQuantidade() - altera a quantidade de um item no carrinho Public Sub setItemQuantidade(ByVal produtoId As Integer, ByVal quantidade As Integer) ' Se estamos definindo a quantidade para 0 , remove o item If quantidade = 0 Then RemoveItem(produtoId) Return End If ' Procura o item e autaliza a quantidade Dim atualizaItem = New CarrinhoItem(produtoId) For Each item As CarrinhoItem In Items If item.Equals(atualizaItem) Then item.Quantidade = quantidade Return End If Next End Sub ' RemoveItem() - Remove um item do carrinho Public Sub RemoveItem(ByVal produtoId As Integer) Dim itemRemovido = New CarrinhoItem(produtoId) For Each item As CarrinhoItem In Items If item.Equals(itemRemovido) Then Items.Remove(item) Return End If Next End Sub #End Region ' GetSubTotal() - retorn ao preco total de todos os itens antes dos impostos Public Function GetSubTotal() As Decimal Dim subTotal As Decimal = 0 For Each item As CarrinhoItem In Items subTotal += item.PrecoTotal Next Return subTotal End Function End Class |
Agora vamos incluir um novo web form no projeto via menu WebSite -> Add New Item selecionando o template Web Form e aceitando o nome Default.aspx.
Vamos usar o controle LinkButton e construir o seguinte leiaute no formulário Default.aspx:
A seguir vamos incluir o código abaixo no code-behind arquivo Default.aspx.vb:
Partial Class _Default Inherits System.Web.UI.Page Protected Sub lnkInclui1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkInclui1.Click ' Incluir o produto 1 no carrinho CarrinhoCompras.Instancia.AddItem(1) ' Redireciona o usuário para ver o carrinho Response.Redirect("VerCarrinho.aspx") End Sub Protected Sub lnkInclui2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkInclui2.Click CarrinhoCompras.Instancia.AddItem(2) Response.Redirect("VerCarrinho.aspx") End Sub Protected Sub lnkInclui3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkInclui3.Click CarrinhoCompras.Instancia.AddItem(3) Response.Redirect("VerCarrinho.aspx") End Sub Protected Sub lnkInclui4_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkInclui4.Click CarrinhoCompras.Instancia.AddItem(4) Response.Redirect("VerCarrinho.aspx") End Sub End Class |
Este código apenas cria uma instância dos itens e inclui no carrinho de compras redirecionando para a página que exibe o carrinho.
Vamos criar agora a página VerCarrinho.aspx que exibe os itens do carrinho realizando a totalização e o controle da quantidade dos itens.
No menu WebSite clique em Add New Item e selecione o template Web Form e informe o nome VerCarrinho.aspx
Neste web forma inclua um controle GridView(ID=gvCarrinhoCompras) e um controle Button(ID=btnAtualizarCarrinho) conforme o leiaute abaixo:
Defina a propriedade DataKeyNames do GridView como ProdutoId e a proriedade GridLines = None;
O código desta página é exibido a seguir:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="VerCarrinho.aspx.vb" Inherits="ViewCart" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Carrinho de Compras</title> <link href="Styles/Estilo.css" rel="stylesheet" type="text/css" /> <style type="text/css"> .style1{color: #0066CC;} .style2{color: #000066;} </style> </head> <body> <form id="form1" runat="server"> <div class="container"> <h1><asp:Image ID="Image1" runat="server" ImageUrl="~/maco10.jpg" /> - <span class="style1">Loja Virtual</span></h1> <a href="Default.aspx" class="style2"><strong>< Continuar Comprando</strong></a> <br /><br /> <asp:GridView runat="server" ID="gvCarrinhoCompras" AutoGenerateColumns="False" EmptyDataText="Não há nenhum item no seu carrinho de compras." GridLines="None" Width="100%" CellPadding="5" ShowFooter="True" DataKeyNames="ProdutoId" OnRowDataBound="gvCarrinhoCompras_RowDataBound" OnRowCommand="gvCarrinhoCompras_RowCommand"> <HeaderStyle HorizontalAlign="Left" BackColor="#3D7169" ForeColor="#FFFFFF" /> <FooterStyle HorizontalAlign="Right" BackColor="#6C6B66" ForeColor="#FFFFFF" /> <AlternatingRowStyle BackColor="#F8F8F8" /> <Columns> <asp:BoundField DataField="Descricao" HeaderText="Descrição" /> <asp:TemplateField HeaderText="Quantidade"> <ItemTemplate> <asp:TextBox runat="server" ID="txtQuantidade" Columns="5" Text='<%# Eval("Quantidade") %>'></asp:TextBox><br /> <asp:LinkButton runat="server" ID="btnRemove" Text="Remover" CommandName="Remove" CommandArgument='<%# Eval("ProdutoId") %>' style="font-size:12px;"></asp:LinkButton> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="PrecoUnitario" HeaderText="Preço" ItemStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Right" DataFormatString="{0:C}" > <HeaderStyle HorizontalAlign="Right"></HeaderStyle> <ItemStyle HorizontalAlign="Right"></ItemStyle> </asp:BoundField> <asp:BoundField DataField="PrecoTotal" HeaderText="Total" ItemStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Right" DataFormatString="{0:C}" > <HeaderStyle HorizontalAlign="Right"></HeaderStyle> <ItemStyle HorizontalAlign="Right"></ItemStyle> </asp:BoundField> </Columns> </asp:GridView> <br /> <asp:Button runat="server" ID="btnAtualizarCarrinho" Text="Atualiza Carrinho" OnClick="btnAtualizarCarrinho_Click" /> </div> </form> </body> </html> |
Note que criamos um templateField para o exibir a quantidade de itens vinculado a propriedade Quantidade da classe CarrinhoItem.
Definimos também dois eventos:
O evento RowDataBound é disparado quando um linha de dados (representado pelo objeto GridViewRow) é vinculado aos dados em um controle GridView. Isto permite implementar um tratamento de evento para realizar operações que alterem as propriedades dos dados vinculados a linha sempre que o evento ocorrer.
O código do arquivo code-behind VerCarrinho.aspx.vb é mostrado a seguir:
Partial Class VerCarrinho Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' ASP.NET gerencia o estado de todos os controles de servidor ' (como o GridView). Por isso, não precisamos fornece a ele os dados ' toda a vez que a pagina carrega somente se não for um postback If Not IsPostBack Then BindData() End If End Sub Protected Sub BindData() ' Atribui os dados ao GridView ' O GridView irá tomar os itens do carrinho um a um e usar as propriedades ' que declaramos como sendo os nomes das colunas gvCarrinhoCompras.DataSource = CarrinhoCompras.Instancia.Items gvCarrinhoCompras.DataBind() End Sub Protected Sub gvCarrinhoCompras_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles gvCarrinhoCompras.RowDataBound ' Se estamos vinculando no rodape vamos adicionar o total If e.Row.RowType = DataControlRowType.Footer Then e.Row.Cells(3).Text = "Total: " & CarrinhoCompras.Instancia.GetSubTotal().ToString("C") End If End Sub ' Este método responde ao evento Click do botão Remover Protected Sub gvCarrinhoCompras_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) Handles gvCarrinhoCompras.RowCommand If e.CommandName = "Remove" Then Dim produtoId = Convert.ToInt32(e.CommandArgument) CarrinhoCompras.Instancia.RemoveItem(produtoId) End If ' temos que redefinir os dados para atualizar a exibi~ção BindData() End Sub Protected Sub btnAtualizarCarrinho_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAtualizarCarrinho.Click For Each row As GridViewRow In gvCarrinhoCompras.Rows If row.RowType = DataControlRowType.DataRow Then ' Vamos usar um bloco try/catch no caso de algum outro codigo de produto for informado Try ' Pega o codigo do produto na propriedade datakeys do GridView Dim produtoId = Convert.ToInt32(gvCarrinhoCompras.DataKeys(row.RowIndex).Value) ' Encontra o TextBox da quantidade e retorna o valor Dim quantidade = Integer.Parse(CType(row.Cells(1).FindControl("txtQuantidade"), TextBox).Text) CarrinhoCompras.Instancia.setItemQuantidade(produtoId, quantidade) Catch ex As FormatException 'Throw ex End Try End If Next ' temos que redefinir os dados para atualizar a exibi~ção BindData() End Sub End Class |
Executando o projeto iremos obter a pagina Default.aspx:
Após incluir alguns itens no carrinho e/ou clicar no link - Ver Carrinho - teremos:
Podemos alterar a quantidade e clicar no botão Atualiza Carrinho para atualizar os valores.
Para excluir um item informe o valor 0 e clique em Atualiza Carrinho ou clique no link Remover.
Pegue o projeto completo com os exemplos aqui : CarrinhoComprasVB.zip
João 6:35
Declarou-lhes Jesus. Eu sou o pão da vida; aquele que vem a mim, de modo algum terá fome, e quem crê em mim jamais tará sede.Referências: