ASP .NET - GridView Aninhados com jQuery e Entity Framework - II


Neste artigo vou mostrar como podemos aninhar dois controles GridViews para exibir os dados em um relacionamento mestre detalhes.

Na primeira parte do artigo criarmos o projeto, definimos o modelo de entidades e a classe que acessa os dados do cliente e dos respectivos pedidos e referenciamos a biblioteca jQuery no projeto.

Vamos continuar definindo a interface com o usuário na página Default.aspx , o arquivo de estilo e o código JavaScript para ocultar e exibir a div dos dados do pedido.

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.

Definindo as imagens usadas o arquivo de estilo da página

Vamos criar duas pastas no projeto:

  1. A pasta CSS onde iremos criar o arquivo de estilo Site.css
  2. A pasta Imagens onde iremos incluir as duas imagens usadas na interface;

Selecione o projeto e no menu Project clique em New Folder e informe o nome CSS;

Repita o procedimento acima e crie a pasta Imagens;

Clique com o botão direito sobre a pasta CSS e a seguir em Add -> New Item;

Clique na guia Web, selecione o template Style Sheet e informe o nome Site.css;

Inclua o código abaixo no arquivo Site.css:

.gvHeader th
{
    padding: 7px;
    background-color: #1A4C1A;
    color: #fff;
    border: 1px solid #bbb;
    font-weight:normal;
}
.gvChildHeader th
{
    padding: 4px;
    background-color: #999966;
    color: #fff;
    border: 1px solid #bbb;
    font-weight:normal;
}
.gvRow td
{
    padding: 7px;
    background-color: #ffffff;
    border: 1px solid #bbb;
}
.gvAltRow td
{
    padding: 7px;
    background-color: #f1f1f1;
    border: 1px solid #bbb;
}
.collapsed-row
{
    display:none;
    padding:1px;
    margin:1px;
}

Este arquivo de estilo define o estilo aplicado aos GridViews que estarão aninhados no projeto.

A seguir clique com o botão direito sobre a pasta Imagens e a seguir em Add -> Existing Item;

Selecione duas imagens que serão usadas para indicar o cliente e os pedidos do cliente. Eu estou usando os arquivos close1.png e open1.png:

Agora podemos definir a interface com o usuário.

Criando a interface com o usuário na página Default.aspx

Abra o arquivo Default.aspx e no modo source inclua o código abaixo neste arquivo:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GridView_Aninhados.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>GridViews Aninhados : Clientes -> Pedidos</title>
    <script src="Scripts/jquery-2.2.3.min.js"></script>
    <link href="CSS/Site.css" rel="stylesheet" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
      <asp:GridView ID="gvCustomers" runat="Server"
                 DataKeyNames="CustomerID"   Width="100%"  GridLines="None"
                 HeaderStyle-CssClass="gvHeader"  CssClass="gvRow"  AlternatingRowStyle-CssClass="gvAltRow"
                 AutoGenerateColumns="False"  OnRowDataBound="gvCustomers_RowDataBound">
      <Columns>

        <asp:TemplateField>
            <ItemTemplate>
                <img src="/imagens/close1.png"  onclick="ExibirOcultar(this, 'tr<%# Eval("CustomerID") %>')" />
            </ItemTemplate>
        </asp:TemplateField>

        <asp:BoundField DataField="CustomerID" HeaderText="ID" />
        <asp:BoundField DataField="ContactName" HeaderText="Cliente" />
        <asp:BoundField DataField="Address" HeaderText="Endereço" />
        <asp:BoundField DataField="City" HeaderText="Cidade" />
        <asp:BoundField DataField="Country" HeaderText="País" />
        <asp:TemplateField  HeaderText="Fone">
           <ItemTemplate>
             <%# Eval("Phone") %>
             <%# NovaLinha(Eval("CustomerID")) %>                     

                <asp:GridView ID="gvOrders" runat="server"   Width="100%"
                    GridLines="None"  AutoGenerateColumns="false"  DataKeyNames="CustomerID"
                    HeaderStyle-CssClass="gvChildHeader"  CssClass="gvRow"  style="padding:0; margin:0"
                    AlternatingRowStyle-CssClass="gvAltRow">
                    <Columns>
                       <asp:BoundField DataField="OrderID" HeaderText="Cod. Pedido" />
                       <asp:BoundField DataField="OrderDate" HeaderText="Data"  DataFormatString="{0:MM-dd-yy}" />
                       <asp:BoundField DataField="ShippedDate" HeaderText="Enviado em"  DataFormatString="{0:MM-dd-yy}" />
                       <asp:BoundField DataField="ShipName" HeaderText="Enviado Para" />
                       <asp:BoundField DataField="ShipCity" HeaderText="Cidade" />
                    </Columns>

               </asp:GridView>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>    
</div>
</form>
</body>
</html>

Neste código definimos dois gridviews :

  1. gvCustomers - exibe os dados dos clientes
  2. gvOrders - exibe os pedidos de um cliente

Referenciamos também a biblioteca jQuery e o arquivo de estilo usado no projeto :

    <script src="Scripts/jquery-2.2.3.min.js"></script>
    <link href="CSS/Site.css" rel="stylesheet" />

Definimos a propriedade DataKeyNames de ambos os gridviews igual a "CustomerID" pois vamos usar o código do cliente atual para obter seus respectivos pedidos.

Note que a primeira coluna é um TemplateField no qual usaremos nossa imagem para mostrar/ocultar os pedidos.

Nesta coluna, nós adicionamos uma imagem com o evento onclick para mostrar/ocultar, onde  ExibirOcultar é uma função do JavaScript no qual passamos dois parâmetros, um a o this , para mudar a imagem da seta e outro é o CustomerID que temos para mostrar ou ocultar.

A última coluna é outro TemplateField que mostra o número de telefone e no qual chamamos o método NovaLinha() passando o código do cliente (CustomerId) para criar o Id da linha e a nova linha.

Neste TemplateField adicionamos nosso gridview filho (gvOrders) e vinculamos as colunas que vincularemos em tempo de execução no evento OnRowDataBound.

Definindo o código da página Default.aspx no code-behind

Agora precisamos definir o código da página Default.aspx no arquivo code-behind Default.aspx.cs.

Abra o arquivo Default.aspx.cs e defina os namespaces abaixo:

using System;
using
System.Web.UI.WebControls;
using
GridView_Aninhados.Models;

Depois no evento Load da página inclua o código abaixo:

 protected void Page_Load(object sender, EventArgs e)
  {
            if (!IsPostBack)
                VinculaGrid();
 }

O código do método VinculaGrid() é dado  seguir:

        private void VinculaGrid()
        {
            var repositorio = new ClienteRepositorio();
            var clientes = repositorio.GetCustomers(1, 10);
            gvCustomers.DataSource = clientes;
            gvCustomers.DataBind();
        }

Este código acessa os dados dos clientes e os exibe no gridview gvCustomers.

Crie o método NovaLinha() que recebe o código do cliente (customerid)  e cria uma nova linha no grid para conter o gridview gvOrders e exibir os pedidos:

        public String NovaLinha(object customerId)
        {
            /* 
                * 1. Fecha a célula atual (Phone)
                * 2. Fecha a linha Atual
                * 3. Cria uma nova linha com o ID e a classe <TR id='...' style='...'>
                * 4. Cria uma célula em branco: <TD></TD>
                * 5. Cria uma nova célula para conter o gridview gvOrders
                ************************************************************/
            return String.Format(@"</td></tr><tr id ='tr{0}' style='collapsed-row'>
               <td></td><td colspan='100' style='padding:0px; margin:0px;'>", customerId);
        }

Para concluir inclua o código a seguir no evento RowDataBound do controle GridView gvCustomers:

        protected void gvCustomers_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                string customerId = gvCustomers.DataKeys[e.Row.RowIndex].Value.ToString();
                var gvOrders = (GridView)e.Row.FindControl("gvOrders");
                var repositorio = new ClienteRepositorio();
                var pedidos = repositorio.GetCustomerOrders(customerId);
                gvOrders.DataSource = pedidos;
                gvOrders.DataBind();
            }
        }

Este código obtém os pedidos de cliente selecionado atribuindo ao gridview gvOrders que esta aninhado com o gridview gvCustomers.

O toque final fica por conta do código JavaScript que iremos incluir entre as tags <head> do arquivo Default.aspx que irá ocultar/exibir os pedidos do cliente:

  <script type="text/javascript">

    function ExibirOcultar(img, div) {
        var current = $('#' + div).css('display');
        if (current == 'none') {
            $('#' + div).show('slow');
            $(img).attr('src', '/imagens/open1.png');
        }
        else {
            $('#' + div).hide('slow');
            $(img).attr('src', '/imagens/close1.png');
        }
    }

</script>

Executando o projeto iremos obter:

1-  A página Default.aspx exibindo os 10 clientes da tabela Customers ordenados por ContactName :

2- Clicando na imagem da primeira coluna do gridview iremos obter os 3 pedidos do respectivo cliente:

Pegue o projeto completo aqui :  GridView_Aninhados.zip (sem referências)

Ninguém pode servir a dois senhores; porque ou há de odiar um e amar o outro, ou se dedicará a um e desprezará o outro. Não podeis servir a Deus e a Mamom.
Mateus 6:24

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

 

Referências:


José Carlos Macoratti