msdn06_capa.JPG

Clique aqui para ler todos os artigos desta edição

 

Paginação no lado cliente para DataGrids

por Jeff Prosise

 

Os desenvolvedores têm uma relação de amor e ódio com o controle DataGrid do ASP.NET. Por um lado, os DataGrids simplificam enormemente a tarefa de processar fontes de dados em tabelas HTML elegantes. Por outro, eles fazem a maior parte do trabalho no lado servidor, fazendo com que as páginas sejam retornadas (Postback) ao servidor com mais freqüência do que os desenvolvedores gostariam. Um DataGrid paginável, por exemplo, é enviado para o servidor a cada vez que o usuário navega entre as páginas. Os postbacks reduzem a performance e inibem a agilidade de resposta. Não é à toa que a maioria dos desenvolvedores sonha com um DataGrid mais eficiente, que percorra os registros sem precisar realizar postbacks repetidamente ao servidor.

Conceitualmente, criar uma tabela HTML paginável que faça a paginação no lado cliente não é difícil, graças à mágica da criação de scripts no lado cliente. A página HTML na Listagem 1 mostra uma técnica para implementar paginações no lado cliente. Quando visualizada em um navegador (veja a Figura 1), a página exibe o que se assemelha a uma tabela. Mas na verdade existem três tabelas encapsuladas em elementos

. O atributo de estilo anexado a cada
assegura que somente uma tabela seja visível por vez, e algumas linhas de JavaScript vinculadas de forma programática aos links Previous e Next ocultam o
que é exibido no momento, enquanto torna visíveis os
anterior ou próximo. O aparecimento e desaparecimento das tabelas criam a ilusão que apenas uma tabela é usada para percorrer (paginar) os registros.

 

Listagem 1 PagingTable.html

 

 

 

 

 

 

Page 1 Page 1 Page 1
Page 1 Page 1 Page 1
Page 1 Page 1 Page 1

 

 

 

 

 

 

Page 2 Page 2 Page 2
Page 2 Page 2 Page 2
Page 2 Page 2 Page 2

 

 

 

 

 

 

Page 3 Page 3 Page 3
Page 3 Page 3 Page 3
Page 3 Page 3 Page 3

Prev 

Next

 

image001.gif

Figura 1 Tabela HTML paginável

 

A mesma técnica pode ser usada para criar DataGrids que suportem paginação no lado cliente. O desafio é modificar a classe DataGrid de modo a produzir uma saída semelhante à da  Listagem 1. Caso você não tenha adivinhado, é exatamente disso que este artigo: melhorar o controle DataGrid ASP.NET por meio da criação de um plug-in que efetue paginações no cliente. Além de adicionar uma nova ferramenta útil à sua toolbox, este é um exemplo maravilhoso de como modificar controles ASP.NET, derivando a partir deles e adicionando funcionalidade por conta própria.

 

Introduzindo o controle ClientPageDataGrid

ClientPageDataGrid é um classe derivada do DataGrid que adiciona suporte à paginação no lado cliente ao ASP.NET. Como ela é uma substituta funcional do DataGrid, você pode usá-la da mesma maneira que usaria um DataGrid. A paginação no lado cliente é totalmente gratuita e pode inclusive ser desativada.

A página da Web na Listagem 2 faz a paginação de maneira normal: efetuando postbacks repetidamente para o servidor. Ela armazena um DataGrid que é configurado para paginar sua saída (AllowPaging="true") e mostrar 16 registros por página (PageSize="16"). Clicar em uma das setas no paginador na parte inferior da grade gera um postback para o servidor e aciona um evento PageIndexChanged, ativando o método OnNewPage. O método OnNewPage define a propriedade CurrentPageIndex do DataGrid para o índice da página anterior ou próxima, fazendo assim com que essa página seja processada de volta para o cliente.

 

Listagem 2 ServerPaging.aspx

 

       doPostBack('MyDataGrid$_ctl20$_ctl0','')">

    

        _doPostBack('MyDataGrid$_ctl20$_ctl1','')">

     >

 

 

Veja agora o mesmo paginador processado por um controle ClientPageDataGrid:

 

 

        _onPrevPage ('MyDataGrid');">< 

       __onNextPage ('MyDataGrid');">>

 

 

As funções JavaScript referenciadas nas tags anchor são registradas quando ClientPageDataGrid.OnPreRender chama Page.RegisterClientScriptBlock. Chamar RegisterClientScriptBlock assegura que o bloco de scripts que contém as funções seja incluído na saída apenas uma vez, mesmo que a página contenha várias instâncias do controle ClientPageDataGrid.

Embora o paginador ClientPageDataGrid por si só não induza nenhum postback, é possível que outros controles na página o façam — e provavelmente o farão. Isso apresenta dois desafios. Primeiro, é necessário atualizar ClientCurrentPageIndex quando ocorrer um postback, a fim de que o código no lado servidor possa determinar qual página estava sendo exibida no momento do postback. Segundo, o ClientPageDataGrid submetido de volta ao cliente após o postback deve preservar a página atual. Em outras palavras, se Page 3 for exibida durante o postback da página para o servidor, os códigos de renderização de ClientPageDataGrid devem anexar um atributo ao elemento

que representa a Page 3, em vez de no elemento
que representa a Page 1.

Para solucionar esses desafios, ClientPageDataGrid registra um campo hidden denominado controlid__ PAGENUM:

Page.RegisterHiddenField (ClientID + "__PAGENUM",

    ClientCurrentPageIndex.ToString ());

 

Listagem 6 Método UpdatePager

void UpdatePager (int page)

{

  // Obter uma referência ao paginador

  TableCell pager = null;

  for (int i = Controls[0].Controls.Count - 1; i >=0; i—) {

     if (((DataGridItem) Controls[0].Controls[i]).ItemType ==

        ListItemType.Pager)

     {

        pager = (TableCell) Controls[0].Controls[i].Controls[0];

        break;

     }

  }

 

  if (PagerStyle.Mode == PagerMode.NextPrev)

  {

    // Implementar um paginador Next-Prev

    // no lado cliente

   pager.Controls.Clear ();

   pager.Controls.Add (CreatePrevPageControl (page));

   pager.Controls.Add (new LiteralControl

                      (" "));

   pager.Controls.Add (CreateNextPageControl (page));

  }

  else if (PagerStyle.Mode == PagerMode.NumericPages)

  {

   pager.Controls.Clear ();

   if (ClientPageCount <= PagerStyle.PageButtonCount)

   {

     // Implementar um paginador numérico no

     // estilo "1 2 3"

     for (int i=0; i