Desenvolvimento - ASP. NET

ASP.NET - DataGrid com CheckBox e Paginação

Estamos de volta nesse artigo dessa vez para demonstrar a utilização do DataGrid em conjunto com o CheckBox, combinando código em JavaScript no cliente com o código .NET dentro do servidor.

por Ramon Durães



Estamos de volta nesse artigo dessa vez para demonstrar a utilização do DataGrid em conjunto com o CheckBox, combinando código em JavaScript no cliente com o código .NET dentro do servidor. Sobre o componente DataGrid realmente você já deve está muito bem informado, pois é um dos componentes mais utilizados no ASP.NET face a sua enorme capacidade de expansão já demonstrada em diversos artigos. Outro grande recurso do DataGrid é a capacidade de realizar paginação, porém quando você insere uma coluna com o recurso do CheckBox e efetua paginação, quando volta à pagina, você perde a persistência de uma seleção anterior dos itens no CheckBox que se tenha feito. Esse artigo também soluciona esse problema utilizando o próprio ViewState (Bolsa de Estado ou Persistência) para armazenar a informação do CheckBox e manter os itens selecionados anteriormente. Vide modelo na Figura 01.


Figura 01 - DataGrid com CheckBox

DataGrid

Para esse projeto insira uma nova pagina pelo Solution Explorer>Aplicação>Add web form e coloque o nome de DataGrid_CheckBox.aspx depois insira um DataGrid (ID=dgConsulta) arrastando do ToolBox conforme Figura 02. Modifique o ID do DataGrid para dgConsulta e seu layout clicando com botão direito no mesmo e escolhendo AutoFormat, definindo um formato de sua preferência.


Figura 02 - DataGrid

A primeira coisa a fazer para esse nosso exemplo é adicionar uma nova coluna do DataGrid e incluir na mesma o controle CheckBox, no DataGrid iremos utilizar uma coluna do tipo TemplateColumn para realizar esse feito. Portanto clique no DataGrid com botão direito e escolha opção Property Build>Collumns conforme Figura 03 adicione uma coluna TemplateColumn.


Figura 03 - Adicionando uma TemplateColumns

Com essa nova coluna adicionada, confirme e retorne ao layout, clique novamente no DataGrid depois em Edit Template>Columns[0] para com isso editarmos essa nova coluna(TemplateColumn). Em modo de edição da coluna arraste um CheckBox (ID=ckHeader) para o Campo Header e outro CheckBox(ID=ckItem) para o campo Edit conforme Figura 4.


Figura 04 - Adicionando CheckBox ao TemplateColumn

Após adicionar o CheckBox lembre de modificar o ID conforme Figura 04. Então finalize a edição clicando novamente com botão direito no DataGrid e escolhendo End Template Editing, o DataGrid deve retornar ao normal e já exibir o CheckBox conforme Figura 05.


Figura 05 - Exibindo CheckBox

A nossa primeira funcionalidade será em JavaScript, para ativar o CheckBox(ckHeader) e adicionar um evento no cliente fazendo com se ele for alterado, altere os outros no estilo marcar todos ou desmarcar. Então no aspx clique em para visualizar o código fonte e adicione o conteúdo da Listagem 01 lembrando de incluir o código completo inclusive substituindo o atual da pagina.

Listagem 01 - Adicionando JavaScript o ASPX da pagina

<body onload="desselecionarTodos();" MS_POSITIONING="GridLayout"> 
            <script language="javascript"> 

/**
// Créditos JavaScript / 2004
-> Ramon Durães e Thiago Monaco
**/ 
      
function selecionarTodos(ckall) { 
   var actVar = ckall.checked ;
   for(i=0; i<Form1.length; i++) {
      if (Form1.elements[i].type == "checkbox") {
         if (Form1.elements[i].name.indexOf("ckItem") != -1) {
            Form1.elements[i].checked = actVar;
         }
      }
   }
}
            
function desselecionarTodos() { 
   var status=true; 
   for(i=0; i<Form1.length; i++) { 
      if (Form1.elements[i].type == "checkbox" && Form1.elements[i].name != "ckHeader") { 
         if (Form1.elements[i].name.indexOf("ckItem") != -1) { 
            if (Form1.elements[i].checked==false){ 
               status=false; 
            }                                   
         } 
      } 
   }                                   

// Rode a pagina e visualizando código no browser certifique que o ckHeader está com esse nome,
// Caso contrário modifique.
// Nome: dgConsulta__ctl1_ckHeader 

         var control = document.getElementById("dgConsulta__ctl1_ckHeader");
         if( control != null ){control.checked=status;}         

          } 

</script> 

Adicionado o código, retorne ao modo Design efetue dois cliques na pagina, e depois adicione o código da Listagem 2, o objetivo desse código é adicionar ao ckHeader e ao ckItem uma chamada para o JavaScript que adicionamos na pagina e configurar o DataGrid para acessar o banco de dados.

Listagem 02 - Adicionando código ao evento dgConsulta_ItemCreated

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

        If Not Me.Page.IsPostBack Then
            carregadg()
        End If 

End Sub 
Private Sub dgConsulta_ItemCreated(ByVal sender As Object, _
   ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _
   Handles dgConsulta.ItemCreated 

        "////////////////////////////////////////
        "// Adicionando JavaScript ao CheckBox //
        "//////////////////////////////////////// 

        If e.Item.ItemType = ListItemType.Header Then 

            Dim ck As CheckBox = CType(e.Item.FindControl("ckHeader"), CheckBox) 

            If Not IsNothing(ck) Then 

                ck.Attributes.Add("onclick", "selecionarTodos(this);") 

            End If 

        End If 

        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then 

            Dim ck As CheckBox = CType(e.Item.FindControl("ckItem"), CheckBox) 

            If Not IsNothing(ck) Then 

                ck.Attributes.Add("onclick", "desselecionarTodos();") 

            End If 

        End If 

        "/////////////// Fim ///////////// 

End Sub

Sub carregadg() 
        Dim connstring As String = _
	   "Password=;User ID=sa;Initial Catalog=Northwind;Data Source=127.0.0.1"
        Dim conn As New System.Data.sqlclient.SqlConnection(connstring)
        Dim cmd As New System.Data.sqlclient.SqlCommand
        Dim da As New System.Data.sqlclient.SqlDataAdapter
        Dim dt As New DataTable
        cmd.Connection = conn
        cmd.CommandType = CommandType.Text
        cmd.CommandText = "Select ProductID,ProductName from Products"
        da.SelectCommand = cmd
        da.Fill(dt)
        da.Dispose()
        cmd.Dispose()
        conn.Dispose()
        dgConsulta.DataSource = dt
        dgConsulta.DataBind()
End Sub

Até esse ponto se testarmos nosso DataGrid já podemos obter o resultado da Figura 05. Se clicar no CheckBox(ckHeader) o JavaScript vai modificar automaticamente os outros itens.


Figura 05 - DataGrid com JavaScript já funcionando

Adicionando Paginação

O recurso de paginação no DataGrid é muito simples retorne ao Property Builder e modique o Allowpaging para True de acordo com Figura 6, depois retorne ao código e adicione a Listagem 03 no evento dgConsulta_PageIndexChanged.


Figura 06 - Configurando paginação (Allow Paging=true)

Após confirmar vá a janela de propriedades do DataGrid e configure a propriedade DataKeyField para "ProductID" .

Listagem 03 - Adicionando paginação

Private Sub dgConsulta_PageIndexChanged(ByVal source As Object, _
   ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) _
	 Handles dgConsulta.PageIndexChanged 
        dgConsulta.CurrentPageIndex = e.NewPageIndex 
        carregadg() 

End Sub 

Estabelecida a configuração você de obter o mesmo resultado da Figura 07, o DataGrid já deve está paginando e exibindo os dados. Porém se você selecionar um item, avançar para uma pagina, quando retornar ele não vai mais ficar selecionado.


Figura 07 - Paginando mas não mantém persistência da seleção no Check

Mantendo persistência no CheckBox durante paginação

Para manter a persistência vamos utilizar um novo método chamado de SalvaCheck e outro chamado de RecuperaCheck que em conjunto salvam em um Array no viewstate informação do CheckBox selecionado permitindo a recuperação. Portanto modifique seu código conforme a Listagem 04.

Listagem 04 - Adicionando persistência ao CheckBox

Private Sub dgConsulta_PageIndexChanged(ByVal source As Object, _
   ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) _
	 Handles dgConsulta.PageIndexChanged 

        SalvaCheck("ckItem", Me.dgConsulta) "Persistindo
        dgConsulta.CurrentPageIndex = e.NewPageIndex
        carregadg()
        RecuperaCheck("ckItem", Me.dgConsulta) "Recuperando 

End Sub 

Sub SalvaCheck(ByVal Nome_Check As String, ByVal DataGrid As DataGrid) 

        "/-------------------------------------------------/ 

        " Ler chebox e grava em um array no viewstate 

        "/------------------------------------------------/ 

        Dim arr As ArrayList = CType(viewstate("arr_" + Nome_Check), ArrayList)
        If IsNothing(arr) Then
            arr = New ArrayList
        End If 

        Dim dgitem As DataGridItem 

        Dim ck As CheckBox 

        For Each dgitem In DataGrid.Items 

            ck = CType(dgitem.FindControl(Nome_Check), CheckBox) 

            If Not IsNothing(ck) Then 

                Dim id As Int32 = Convert.ToInt32(DataGrid.DataKeys(dgitem.ItemIndex)) 

                Dim Find As Boolean = arr.Contains(id) 

                If Find And Not ck.Checked Then 

                    arr.Remove(id) " Remove do array 

                ElseIf Find = False And ck.Checked Then 

                    arr.Add(id) " Adiciona ao Array 

                End If 

            End If 

        Next 

        viewstate("arr_" + Nome_Check) = arr 

End Sub 


Sub RecuperaCheck(ByVal Nome_Check As String, ByVal DataGrid As DataGrid) 

        "/-------------------------------------------------/ 

        " Recupera array viewstate e grava checkbox 

        "/------------------------------------------------/       

        Dim arr As ArrayList = CType(viewstate("arr_" + Nome_Check), ArrayList) 

        If IsNothing(arr) Then 

            arr = New ArrayList 

        Else 

            arr.Sort() 

        End If 

        If arr.Count > 0 Then 

            Dim dgitem As DataGridItem 

            Dim ck As CheckBox 

            For Each dgitem In DataGrid.Items 

                ck = CType(dgitem.FindControl(Nome_Check), CheckBox) 

                If Not IsNothing(ck) Then 

                    Dim id As Int32 = Convert.ToInt32( _
                      DataGrid.DataKeys(dgitem.ItemIndex)) 

                    If arr.Contains(id) Then 

                        ck.Checked = True 

                    End If 

                End If 

            Next 

        End If 

End Sub  

Finalizando

Você aprendeu nesse artigo como paginar registros e como utilizar uma coluna do tipo TemplateColumn, tal como tornar o CheckBox persistente durante a paginação.

O que você gostaria saber?
Aguardo seu comentário! Ele é muito importante. Participe!!! Até próximo artigo!

Você é de Salvador Bahia, então participe do grupo de usuários .NET http://www.mutex.com.br

Ramon Durães

Ramon Durães - Especialista em desenvolvimento de software e Microsoft Most Valuable Professional (MVP) em Visual Studio Team System. Realiza treinamentos de .NET Framework em empresas, consultoria em arquitetura de software e implantação de Visual Studio Team System. Palestrante nos principais eventos da Microsoft no Brasil (Tech-Ed 2005, Tech-Ed 2006, Tech-Ed 2007, Tech-Ed 2008, Tech-ED 2009), Microsoft Innovation Days 2007 (Salvador, Brasília, Recife, Goiânia, Natal, Maringá), Microsoft Innovation Days 2009 (Salvador) , Campus Party Brasil 2009 e eventos regionais relacionados a grupos de usuários e universidades. Conhecido autor de artigos para os principais portais de conteúdo e autor de 10 publicações eletrônicas em CD (Video-Aula) pela editora Linha de Código além dos livros "Desenvolvendo para web usando o Visual Studio 2008" e "Gerenciando projetos de software usando Visual Studio Team System" pela editora Brasport. Pode ser encontrado em seu blog http://www.ramonduraes.net e @ramonduraes no Twitter.