Clique aqui para instalar o Silverlight*
BrasilAlterar|Todos os sites da Microsoft
MSDN
|Developer Centers|Biblioteca|Downloads|Assinaturas MSDN
Pesquisa rápida


DataGrid Aninhados

Por Renato Haddad, Microsoft Most Valuable Professional .NET Compact Framework. Autor de diversos livros e ministra palestras e treinamentos sobre a tecnologia .NET.

Tecnologias Utilizadas

ASP.NET

O objetivo deste artigo é mostrar o uso de DataGrids aninhados, como capturar dados oriundos do DataGrid e submeter um código passando este dado capturado como parâmetro. Faremos todos os exemplos com códigos, sem o uso de assistentes do VS.NET. O banco de dados usado será o Northwind do SQL Server.

Crie um novo projeto em ASP.NET Web Application com Visual Basic chamado MSDN.

Adicione um novo Web Form chamado gridAninhados contendo o seguinte formato e controles:

DropDownList = dropCidades
Label1 = lblValor
DataGrid1 = gridOrders

Columns:

TipoHeaderData FieldData Formatting

Bound Column

Pedido

OrderID

Bound Column

DtPedido

OrderDate

{0:dd/MM/yyyy}

Bound Column

Cidade

ShipCity

Bound Column

CustomerID

CustomerID

Como a primeira coluna é especial, veja as propriedades:

Tipo: Button Column (Select Column)

Text: 4

Command name: Select

Localize a formatação da coluna na figura seguinte e altere a Fonte para Webdings. Isto fará com que o número 4 seja uma seta na exibição da coluna.

Configure o gridOrders para paginação.

DataGrid2 = gridDetails com as seguintes colunas:

TipoHeaderData FieldData Formatting

Bound Column

Produto

ProductName

Bound Column

Preço

UnitPrice

{0:n}

Bound Column

Qtde

Quantity

Bound Column

Total

Total

{0:c}

DataKeyField

A propriedade DataKeyField é a chave do gridOrders, portanto, exiba a janela de propriedades e digite o campo OrderID. O funcionamento desta página ocorrerá da seguinte forma:

Quando a página é carregada pela primeira vez, o dropCidades é carregado com todas as cidades da tabela Orders e já carrega os pedidos da respectiva cidade;

Quando o usuário selecionar um determinado pedido no gridOrders, o código capturado é o descrito no DataKeyField que será a condição da instrução SQL para pesquisar todos os produtos do respectivo pedido;

Este mesmo ID selecionado será usado para pesquisar o valor total do pedido e exibí-lo no lblValor.

Códigos

Neste artigo usarei somente códigos escritos em VB.NET, mas e você programa em C# ou outra linguagem é só adapta-los. A idéia é manter a string de conexão com o banco de dados no arquivo Web.Config e os demais códigos diretamente na página.

Web.Config

Como iremos usar uma conexão com o banco de dados Northwind do SQL Server, abre o arquivo Web.Config e no final, inclua as seguintes linhas para definir uma chave para a “variável” conexao. Note que o local de digitação é muito importante neste caso. Se a sua string de conexão tiver outros parâmetros, por exemplo, senha ou segurança integrada, basta adicionar a esta string.

…
</system.web>
  
  <appSettings>
	<add key="conexao" value="Database=Northwind;Server=(local);user id=sa"/>
  </appSettings>

</configuration>

        

Retorne a página aspx e pressione F7 para exibir a janela de códigos. Antes do evento Page_Load digite o seguinte código para ler a string que contém a conexão com o banco de dados. Cabe ressaltar que esta técnica tem sido muito utilizada nas aplicações ASP.NET para maximizar o código, ou seja, se algum dia mudar a string de conexão com o banco de dados, você altera apenas no arquivo Web.Config.

Dim conexao As String = ConfigurationSettings.AppSettings("conexao")

Functions

Para facilitar o código, crie as seguintes funções:

GetDados – recebe uma instrução SQL como argumento e retorna um DataSet. Aqui é montada uma DataTable chamada “dados” que é preenchida para o DataAdapter do respectivo DataSet que será o retorno da função.

 Public Function GetDados(ByVal sql As String) As DataSet
   Try
      Dim conn As New SqlConnection(conexao)
      Dim da As New SqlDataAdapter(sql, conn)
      Dim ds As New DataSet
      conn.Open()
      da.Fill(ds, "dados")
      conn.Close()
      Return ds
   Catch ex As SqlException
      Throw
   End Try
End Function
        

GetValorPedido – recebe uma instrução SQL como argumento e retorna uma string contendo o valor do pedido passado como parâmetro.

Public Function GetValorPedido(ByVal sql As String) As String
   Try
      Dim conn As New SqlConnection(conexao)
      Dim cmd As New SqlCommand(sql, conn)
      conn.Open()
      Dim valor As String = cmd.ExecuteScalar()
      conn.Close()
      Return valor
   Catch ex As SqlException
      Throw
   End Try
End Function
        

Page_Load

O evento Page_Load é disparado toda vez que a página é carregada. Neste exemplo, o dropCidades deverá ser preenchido somente a primeira vez que a página for carregada. Quem se encarrega de avaliar se é ou não a primeira vez é o IsPostBack.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles MyBase.Load
'Put user code to initialize the page here
   If Not Page.IsPostBack Then
      Dim sql As String = "Select Distinct ShipCity FROM Orders ORDER BY ShipCity"
      With dropCidades
          .DataTextField = "ShipCity"
          .DataValueField = "ShipCity"
          .DataSource = GetDados(sql).Tables("dados").DefaultView
          .DataBind()
      End With
      dropCidades_SelectedIndexChanged(sender, e)
    End If
End Sub
        

Explicação do código

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles MyBase.Load
   'Put user code to initialize the page here

Verifica se algo foi postado

If Not Page.IsPostBack Then

Define a instrução SQL

Dim sql As String = "Select Distinct ShipCity FROM Orders ORDER BY ShipCity"

Configura o dropCidades com o campo a ser exibido (DataTextField) e o campo a ser armazenado (DataValueField).

      With dropCidades
          .DataTextField = "ShipCity"
          .DataValueField = "ShipCity"

Define a fonte de dados que será o retorno da função GetDados, que é um Dataset. Note que a variável SQL é passada como parâmetro. Como na função GetDados é gerada uma tabela chamada “dados”, é esta a ser utilizada como fonte de dados. O DataBind é fundamental para renderizar o controle. É comum novatos em ASP.NET esquecer deste comando, portanto, vá se acostumando.

          .DataSource = GetDados(sql).Tables("dados").DefaultView
          .DataBind()
      End With

Pense comigo: se o dropCidades irá exibir todas as cidades, então porque não exibir os pedidos relativos a primeira cidade da lista a ser exibida no dropCidades? Este comando você deverá inserí-lo apenas após criar o respectivo evento do dropCidades. Note que os parâmetros passados é o próprio objeto atual “sender” e o argumento “e”.

      dropCidades_SelectedIndexChanged(sender, e)
    End If
End Sub

DropCidades

Após exibir todas as cidades o usuário poderá selecionar qualquer cidade para pesquisar todos os pedidos relativos e exibi-los no gridOrders. Portanto, dê um duplo clique no dropCidades e digite o respectivo código. A idéia é usar a mesma função GetDados passando o SQL como parâmetro e usando a DataTable “dados” de retorno. Note ainda que a cada cidade escolhida é atribuído Nothing ao gridDetails, pois é uma forma de zerar o grid.

Private Sub dropCidades_SelectedIndexChanged(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles dropCidades.SelectedIndexChanged
   Dim sql As String
   sql = "Select OrderID, CustomerID, OrderDate, ShipCity FROM Orders "
   sql += "WHERE ShipCity = '" & dropCidades.SelectedItem.Value & "'"
   With gridOrders
       .DataSource = GetDados(sql).Tables("dados").DefaultView
       .DataBind()
   End With
   With gridDetails
       .DataSource = Nothing
       .DataBind()
   End With
End Sub

Capturando cliques no DataGrid

Como todos os pedidos de uma determinada cidade são exibidos no gridOrders, é preciso capturar o item selecionado e montar uma instrução SQL para pesquisar todos os produtos do respectivo pedido. Para isso, selecione o gridDados em Class Name e o evento ItemCommand em Method Name.

Para capturar o item que foi selecionado no Grid, use o comando DataKeys(e.Item.ItemIndex). Este comando retorna exatamente o conteúdo do campo definido na propriedade DataKeyField. Veja o respectivo código:

Private Sub gridOrders_ItemCommand(ByVal source As Object, 
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) 
Handles gridOrders.ItemCommand
   If e.CommandName = "Select" Then
      'pesquisa os detalhes do pedido
      Dim id As Integer = gridOrders.DataKeys(e.Item.ItemIndex)
      Dim sql As New System.Text.StringBuilder
      sql.Append("SELECT [Order Details].OrderID, Products.ProductName,
       [Order Details].UnitPrice, ")
      sql.Append("[Order Details].Quantity, [Order Details].UnitPrice *
       [Order Details].Quantity AS Total ")
      sql.Append("FROM [Order Details] INNER JOIN Products ")
      sql.Append("ON [Order Details].ProductID = Products.ProductID ")
      sql.Append("WHERE [Order Details].OrderID = " & id)
      With gridDetails
           .DataSource = GetDados(sql.ToString).Tables("dados")
           .DataBind()
      End With

     sql.Remove(0, sql.Length)
     sql.Append("SELECT SUM(UnitPrice * Quantity) AS Total ")
     sql.Append("FROM [Order Details] ")
     sql.Append("WHERE OrderID = " & id)
     lblValor.Text = "Total: " + FormatNumber(GetValorPedido(sql.ToString), 2)
  ElseIf e.CommandName = "Page" Then
     With gridDetails
         .DataSource = Nothing
         .DataBind()
     End With
  End If
End Sub

Explicação:

Dispara o evento ItemCommand do gridOrders o qual contém o argumento “e” que retorna os argumentos do objeto gridOrders.

Private Sub gridOrders_ItemCommand(ByVal source As Object, ByVal e As 
System.Web.UI.WebControls.DataGridCommandEventArgs) Handles gridOrders.ItemCommand

Como um DataGrid pode conter vários controles Button Column, é preciso saber qual deles foi clicado pelo usuário. Neste caso é o Select (primeira coluna do grid).

   If e.CommandName = "Select" Then
      'pesquisa os detalhes do pedido

Esta linha captura o valor do conteúdo selecionado no gridOrders e armazena na variável id que será usada na clausula Where do SQL.

      Dim id As Integer = gridOrders.DataKeys(e.Item.ItemIndex)

Define a variável SQL do tipo StringBuilder para poder concatenar textos. Opte sempre por este método quando for manipular qualquer string. É infinitamente mais rápido do que qualquer outro meio de concatenação e manipulação de string que você conheça.

      Dim sql As New System.Text.StringBuilder

Monta a instrução SQL que irá pesquisar todos os produtos relacionados ao respectivo pedido. Para cada bloco é adiciona à variável SQL.

sql.Append("SELECT [Order Details].OrderID, Products.ProductName, [Order Details].UnitPrice, ")
sql.Append("[Order Details].Quantity,[Order Details].UnitPrice * [Order Details].Quantity AS Total")
sql.Append("FROM [Order Details] INNER JOIN Products ")
sql.Append("ON [Order Details].ProductID = Products.ProductID ")
sql.Append("WHERE [Order Details].OrderID = " & id)

Configura as propriedades do gridDetails, o qual chama a função GetDados passando o SQL como parâmetro. Como o retorno sempre será a DataTable “dados”, então a mesma é especificada. Esta linha também poderia ser escrita da seguinte forma, onde ao invés do nome da dataTable é usado o índice: GetDados(sql.ToString).Tables(0). Por fim, use o DataBind para renderizar o grid no servidor.

      With gridDetails
           .DataSource = GetDados(sql.ToString).Tables("dados")
           .DataBind()
      End With

Esta linha remove todo o conteúdo da variável SQL e remonta com uma nova instrução SQL, o qual irá somar o valor do pedido e exibir os dados em lblValor formatado com duas casas decimais.

     sql.Remove(0, sql.Length)
     sql.Append("SELECT SUM(UnitPrice * Quantity) AS Total ")
     sql.Append("FROM [Order Details] ")
     sql.Append("WHERE OrderID = " & id)
     lblValor.Text = "Total: " + FormatNumber(GetValorPedido(sql.ToString), 2)

Caso contrário, ou seja, o usuário não selecionou um pedido, é preciso atribuir Nothing ao gridDetails para não ficar “lixo” na página. Isso ocorrerá em situações de paginação do gridOrders.

  ElseIf e.CommandName = "Page" Then
     With gridDetails
         .DataSource = Nothing
         .DataBind()
     End With
  End If
End Sub

Paginação

Como no gridOrders podem haver diversos pedidos de uma cidade, é preciso disparar o comando de paginação quando for solicitado. Para isso, selecione o gridOrders em Class Name e o evento PageIndexChanged em Method Name.

Digite o seguinte código para controlar a paginação. Note que o número da página é verificado para não haver problemas com o índice. Se for maior ou igual a zero, então é disparado o evento do dropCidades e o DataBind do gridOrders.

Private Sub gridOrders_PageIndexChanged(ByVal source As Object, 
ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) 
Handles gridOrders.PageIndexChanged
   If e.NewPageIndex >= 0 Then
      lblValor.Text = String.Empty
      gridOrders.CurrentPageIndex = e.NewPageIndex
      dropCidades_SelectedIndexChanged(source, e)
      gridOrders.DataBind()
   End If
End Sub

Determine este formulário como default (Set As Start Page) no Solution Explorer e e execute-o no browser (Ctrl + F5).

Selecione outra cidade e veja que existem vários pedidos. Neste caso, como defini que haverá um controle de paginação neste grid, então é exibido automaticamente.

Selecione um determinado pedido e veja que são exibidos todos os produtos relativos ao pedido, assim como o respectivo valor total.

Conclusão

Com esta aplicação você poderá desenvolver excelentes páginas com o controle DataGrid, basta saber como capturar dados e manipular os eventos. Note que com poucos códigos criei uma aplicação funcional e prática para consultas de dados diretament no banco de dados.

Bons estudos e lembre-se: No Stress, think .NET!!!

Renato Haddad (rehaddad@msn.com) é MVP, editor da revista MSDN Magazine Brasil, ministra treinamentos e palestras sobre .NETe autor de diversos livros e treinamentos em CD multimídia de ASP.NET, Visual Studio .NET 2003 e Aplicações Móveis para celulares e Pocket PC, tanto no Brasil como em outros países da América Latina. Autor de 9 livros, entre eles ASP.NET para desenvolvedores ASP, editora Érica.

Referências:

www.asp.net


 

©2017 Microsoft Corporation. Todos os direitos reservados. Entre em contato |Nota Legal |Marcas comerciais |Política de Privacidade
Microsoft