Olá pessoal, neste artigo será criado um projeto para editar dados do GridView, em .NET, utilizando a linguagem C#. Acompanhem:

Em projetos de software, sejam pessoais ou profissionais, é normal que tenhamos a situação em que precisamos ver uma lista de dados e, ao clicar em cada registro desta lista, vermos os detalhes da mesma, em uma nova página. Como essa tarefa já é algo mais do que normal em nossa área (se você ainda não precisou fazer isso, um dia irá precisar!) decidi fazer este artigo, também devido a alguns pedidos dos leitores deste blog.

Crie um projeto em ASP.NET. Para este exemplo usarei o banco de dados Northwind, da Microsoft. Caso não o tenha instalado, clique aqui!.

A tabela que será usada para este exemplo é a Products.

Após instalar o banco e configurar a conexão com o Visual Studio, abra o Web.config e adicione uma chave, responsável por conter a string de conexão com o banco de dados, ilustrado na Listagem 01.


<connectionStrings>
<add name="StringConexao" 
connectionString="Data Source=.\SQLEXPRESS;Initial 
Catalog=Northwind;Integrated Security=True" 
providerName="System.Data.SqlClient"/>
</connectionStrings>
Listagem 01. String de conexão adicionada ao Web.config

Adicione ao projeto uma classe, dando a ela o nome Produtos. Essa classe irá conter a lógica de acesso aos dados. Nela, adicione cinco variáveis públicas, visíveis por toda a classe, como ilustrado pela Listagem 02.


public SqlConnection objConexao;
public SqlCommand objCommand;
public string strStringConexao = 
ConfigurationManager.ConnectionStrings["StringConexao"].ConnectionString;
public string strSelect = "SELECT TOP 10 ProductID, ProductName, UnitPrice,
 UnitsInStock FROM Products";
public string strSelectPorID = "SELECT ProductID, ProductName, UnitPrice, 
UnitsInStock FROM Products WHERE ProductID = @ProductID";
Listagem 02. Variáveis públicas

As duas primeiras variáveis conterão os objetos de conexão e comando do banco de dados, a terceira conterá a string de conexão, recuperada do Web.config, e as duas últimas receberão as instruções SELECT de consulta aos dados.

A Listagem 03 ilustra a classe com as propriedades referentes as colunas do banco que traremos pelas instruções SELECT.


public class ModeloProdutos
{
    public Int32 ProductID { get; set; }
    public String ProductName { get; set; }
    public Decimal UnitPrice { get; set; }
    public Int16 UnitsInStock { get; set; }
}
Listagem 03. Classe Modelo

A Listagem 04 ilustra o método para retornar os produtos do banco de dados, com o auxílio da Listagem 05, que irá iterar pelo DataReader preenchendo a lista com os dados.


public List<ModeloProdutos> ConsultarProdutos()
{
    var lstRetorno = new List<ModeloProdutos>();
    using (objConexao = new SqlConnection(strStringConexao))
    {
        using (objCommand = new SqlCommand(strSelect, objConexao))
        {
            try
            {
                objConexao.Open();
                var objDataReader = objCommand.ExecuteReader();
                if (objDataReader.HasRows)
                    lstRetorno = PreencheValores(objDataReader);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                objConexao.Close();
            }
        }
    }
    return lstRetorno;
}
Listagem 04. Método ConsultarProdutos

public List<ModeloProdutos> PreencheValores(SqlDataReader reader)
{
    var lista = new List<ModeloProdutos>();
    while (reader.Read())
    {
        var modeloProdutos = new ModeloProdutos();
        modeloProdutos.ProductID = Convert.ToInt32(reader["ProductID"].ToString());
        modeloProdutos.ProductName = reader["ProductName"].ToString();
        modeloProdutos.UnitPrice = Convert.ToDecimal(reader["UnitPrice"].ToString());
        modeloProdutos.UnitsInStock = Convert.ToInt16(reader["UnitsInStock"].ToString());
        lista.Add(modeloProdutos);
    }
    return lista;
}
Listagem 05. Método PreencheValores

Com a estrutura praticamente pronta da classe, na próxima parte faremos a parte do layout e os testes práticos com os métodos criados.

Neste momento agora renomeie sua página para Produtos.aspx arraste para a página o controle GridView. Nele, altere suas configurações para que fique parecido com o da Listagem 06.


<asp:GridView ID="grdDados" runat="server" AutoGenerateColumns="false" 
OnRowCommand="grdDados_RowCommand">
<Columns>        
    <asp:BoundField DataField="ProductName" HeaderText="Produto" />
    <asp:BoundField DataField="UnitPrice" HeaderText="Preço Unitário" />
    <asp:BoundField DataField="UnitsInStock" HeaderText="Unidades em 
    Estoque" />
    <asp:TemplateField>
        <ItemTemplate>
            <asp:Button ID="btnEditar" runat="server" 
            CommandName="Editar" Text="Editar Dados"
                CommandArgument='<%# DataBinder
                .Eval(Container.DataItem, "ProductID")%>' />
        </ItemTemplate>
    </asp:TemplateField>
</Columns>
</asp:GridView> 
Listagem 06. GridView de Produtos

A propriedade AutoGenerateColumns deve receber o valor False para que possamos colocar no GridView as tags BoundField, que são simples “containers” de exibição dos dados vindos do banco, enquanto que dentro das tags TemplateField e ItemTemplate conseguimos colocar qualquer tipo de controle ASP.NET e/ou HTML.

Note que é feito uma chamada ao evento RowCommand, que é acionado toda vez que é feito um postback de um controle do GridView que utiliza a propriedade CommandName, como é o caso do botão Editar. Repare que este botão contem também a propriedade CommandArgument, responsável por conter o valor da coluna ProductID, referente ao registro clicado.

Agora vá a página de códigos e carregue os dados no GridView, como ilustra a Listagem 07, onde é feita a chamada ao método criado na parte anterior desta série de artigos.


rotected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        var listaProdutos = new Produtos().ConsultarProdutos();
        if (listaProdutos != null && listaProdutos.Count > 0)
        {
            this.grdDados.DataSource = listaProdutos;
            this.grdDados.DataBind();
        }
    }
}
Listagem 07. Evento Page Load da página de Produtos

Com poucas linhas de código criamos uma lista, instanciamos a classe, chamamos o método para consultar os produtos e atribuímos o valor da lista ao GridView.

Repare no código acima que utilizamos a palavra-chave var, que serve para declararmos uma variável sem se preocupar com seu tipo.

Se testarmos veremos que o GridView já funciona e nos retorna 10 registros. Mais e se quisermos clicar em um registro específico e editar seus dados? Para isso foi criado a chamada ao evento RowCommand. Antes de usarmos ele crie mais uma página em seu projeto, dando a ela o nome DetalheProduto.aspx. Nessa página arraste alguns controles, ilustrados pela Listagem 03.


<asp:TextBox ID="txtProduto" runat="server" 
Width="200px" /><br />
<asp:TextBox ID="txtPrecoUnitario" 
runat="server" /><br />
<asp:TextBox ID="txtUnidadesEstoque" 
runat="server" /><br /><br />
<asp:LinkButton ID="lnkVoltar" runat="server" 
PostBackUrl="~/Produtos.aspx" Text="Voltar" />
Listagem 08. Página de Detalhe do Produto

Agora sim, codifique o evento RowCommand, ilustrado pela Listagem 04.


protected void grdDados_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName.Equals("Editar"))
    {
        string idProduto = e.CommandArgument.ToString();
        if (!String.IsNullOrEmpty(idProduto))
            this.Response.Redirect("DetalheProduto.aspx?IdProduto=" + idProduto);
    }
}
Listagem 09. Evento RowCommand

Basicamente verificamos se o CommandName acionado no GridView é igual ao texto Editar (confirme no botão da Listagem 01), sendo é declarado uma variável que recebe o valor de CommandArgument de e, que contém o ID do Produto, recuperado pelo botão (torne a olhar a Listagem 01 para entender melhor). Após ser feito uma verificação de rotina no valor da variável é feito um redirecionamento para a página criada, de detalhe do produto, passando como parâmetro o ID do Produto.

Para que consigamos retornar o detalhe do produto na página criada, antes é preciso criar o método que fará isso. Ele é similar ao ConsultarProdutos, criado na parte anterior da série de artigos.

As Listagens 10 e 11 ilustram o método e seu auxiliar.


public ModeloProdutos ConsultarProduto(int IdProduto)
{
    var produto = new ModeloProdutos();

    using (objConexao = new SqlConnection(strStringConexao))
    {
        using (objCommand = new SqlCommand(strSelectPorID, objConexao))
        {
            try
            {
                objConexao.Open();
                objCommand.Parameters.AddWithValue("@ProductID", IdProduto);
                var objDataReader = objCommand.ExecuteReader();

                if (objDataReader.HasRows)
                    produto = PreencheValor(objDataReader);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                objConexao.Close();
            }
        }
    }

    return produto;
}
Listagem 10. Método ConsultarProduto

public ModeloProdutos PreencheValor(SqlDataReader reader)
{
    var modeloProdutos = new ModeloProdutos();
    while (reader.Read())
    {
        modeloProdutos.ProductID = Convert.ToInt32(reader["ProductID"].ToString());
        modeloProdutos.ProductName = reader["ProductName"].ToString();
        modeloProdutos.UnitPrice = Convert.ToDecimal(reader["UnitPrice"].ToString());
        modeloProdutos.UnitsInStock = Convert.ToInt16(reader["UnitsInStock"].ToString());
    }
    return modeloProdutos;
}
Listagem 11. Método PreencheValor

Agora sim, temos o método pronto, só chama-lo na página que receberá o ID do produto.


protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        if (Request.QueryString["IdProduto"] != null)
            this.CarregarDetalhesProduto(Convert.ToInt32(Request.QueryString["IdProduto"]));
    }
}
Listagem 12. Evento Page Load da página de Detalhes do Produto

Assim, se tiver valor na QueryString, é recuperado o ID do produto e passado para o método CarregarDetalhesProduto, que é ilustrado pela Listagem 08.


private void CarregarDetalhesProduto(int IdProduto)
{
    var dadosProduto = new Produtos().ConsultarProduto(IdProduto);
    if (dadosProduto != null)
    {
        this.txtProduto.Text = dadosProduto.ProductName;
        this.txtPrecoUnitario.Text = dadosProduto.UnitPrice.ToString();
        this.txtUnidadesEstoque.Text = dadosProduto.UnitsInStock.ToString();
    }
}
Listagem 13. Método CarregarDetalhesProduto

Após ter feito toda essa codificação, nada melhor que testar para ver se tudo ocorreu como esperado!

As Figuras 01 e 02 ilustram os testes, onde cliquei no 1º produto da lista para ver seus detalhes.

Listagem de Produtos
Figura 01. Listagem de Produtos
Detalhe do Produto
Figura 02. Detalhe do Produto

Na próxima parte faremos mais alguns testes e melhorias, adicionando mais controles ao GridView, além de usarmos ViewState e Session para persistir os valores e enviá-los a página de detalhe.

De qualquer forma, o que foi feito até esta parte está disponível para download neste post.

Assim finalizo o artigo. Muito obrigado a todos! Um abraço, e até o próximo artigo.