Datagrid, paginazione e indicizzazione dei dati

"Datagrid, paginazione e indicizzazione dei dati" è il titolo di un mio articolo non ankora pubblicato che tra un pò fermenta (l'idea e le bozza era partota a maggio del 2004)... è qsi tutto fatto, manca un paragrafo - qlllo più importante - e manka poi la traskrizione in italiano - ke ora è in barzaghese :-p
Il punto base dell'articolo riguarda l'indicizzazione dei siti, cioè la catalogazione delle pagine del sito sui motori di ricerca. Un sito per essere indicizzabile deve cioè abbattere tutte qlle barriere architetturali che sono veri e proprio muri per i crawler/robot dei motori di ricerca: button, linkbutton, javascript, post e postback! Ogni contenuto deve non solo avere un indirizzo univoco - anche solo per querystring - ma sarebbe preferibile avesse anche un titolo univoco.
Per chi fosse interessato invito a dare un letta qui "Creare buone strutture di navigazione".
Una delle cose meno indicate per l'indicizzazione sono le pagine polimorfiche... qlle pagine cioè che si modellano e presentano contenuti diversi a colpi di Postback! Un esempio di queste pagine? Banalmente le pagine con datagrid paginate! :-p

Quando ho necessità di avere sito indicizzato e di usare la datagrid adotto la tecnica di usare un mio paginatore che voglio presentare qui.
Ovviamente la mia speranza che dopo averlo scritto in maniera informale qui mi venga voglia di finire articolo che per mancanza di tempo o per stanchezza non trovo mai il tempo di completare... e tutte le volte che ci penso mi piange un poco il c uore visto ke la kosa mi sembra interessante.
Senza commentare troppo come farei in un articolo pubblicato sul canele ufficiale posto qui tutti gli ingredienti per fare qllo ke ci serve.


public abstract class WebUtils
{
 ///
 /// Costruisce query string dato un NameValueCollection
 /// 
 public static string ToQuerystring(NameValueCollection args){   
  StringBuilder sb = new StringBuilder();
  foreach(string key in args.Keys){
   sb.Append(sb.Length == 0 ? string.Empty : "&");
   sb.Append(key);
   sb.Append("=");
   sb.Append(HttpUtility.UrlEncode(args[key]));    
  }
  return sb.ToString();
 }
}

Implemento il mio paginatore. Il paginatore trasformerà in link (tag A di HTML) quelli che nel paginatore standard della datagrid sono linkbutton che fanno uso di javascript e postback. Questa che mostro è la versione semplice del paginatore... poi la si può abbellire e ottimizzare :-p

[ToolboxData("<{0}:PageNavigationControl runat='server'>")]
public class PageNavigationControl: WebControl 
{
 private int pageSize  = 10;
 private int currentPageIndex = -1;
 private int virtualItemCount = 10;
 
 /// 
 /// Legge Current Page Index da querystring
 /// 
 void ReadCurrentPageIndex()
 {
  //a che pagina siamo?
  string qCurrentPageIndex = HttpContext.Current.Request.QueryString[this.ID];     
  if(qCurrentPageIndex != null)
  {
   currentPageIndex = int.Parse(qCurrentPageIndex);
  }
  else
  {
   //...non è inicata nessuna pagina: siamo a pagina 1!
   currentPageIndex = 0;
  }
 }
 /// 
 /// Current page index
 /// 
 public int CurrentPageIndex
 {
  get
  {
   if(currentPageIndex == -1)
    ReadCurrentPageIndex();
   return currentPageIndex;}
 }
 /// 
 /// Page size
 /// 
 public int PageSize
 {
  get{return pageSize;}
  set{pageSize = value;}
 }
 
 /// 
 /// Virtual Item Count
 /// 
 public int VirtualItemCount
 {
  get{return virtualItemCount;}
  set{virtualItemCount = value;}
 }
 /// 
 /// Enables a control to render content to the client browser.
 /// 
 protected override void Render(System.Web.UI.HtmlTextWriter writer) 
 {
  
  //Quante pagine sono?
  int pageCount = virtualItemCount / pageSize + 1;        
  //Quali sono i dati in querystring?
  NameValueCollection args = new NameValueCollection(HttpContext.Current.Request.QueryString);

  //stampo i link per la navigazione...
  for(int i = 0; i < pageCount; i++)
  { 
  
   string pageNumber = (i +1).ToString();
   if(currentPageIndex == i)
   {
    //...nessun link per la pagina corrente...
    writer.Write(pageNumber);
   }
   else
   {
    //aggiungo/modifico nella lista dei dai della querystring il numero di pagina del link     
    args[this.ID] = i.ToString();
    //...stampo numero di pagina...
    UriBuilder href = new UriBuilder(HttpContext.Current.Request.Url);
    href.Query = WebUtils.ToQuerystring(args); 
    writer.AddAttribute(HtmlTextWriterAttribute.Href , href.ToString());
    writer.RenderBeginTag(HtmlTextWriterTag.A);    
    writer.Write(pageNumber);
    writer.RenderEndTag();
   }
   writer.Write(HtmlTextWriter.SpaceChar);
  }
 }
}

Questa è una pagina dove uso il tutto! :-p

public class IndexedPaging : System.Web.UI.Page
{
 protected System.Web.UI.WebControls.DataGrid DataGrid1;
 protected PageNavigationControl PageNavigationControl1;

 #region BindDataGrid
 private void BindDataGrid(){

  //Recupero il numero di Record nella tabella Products del Northwind
  PageNavigationControl1.VirtualItemCount = Products.RetrieveRecordCount();

  int start = PageNavigationControl1.CurrentPageIndex * PageNavigationControl1.PageSize;
  int max = PageNavigationControl1.PageSize;
  
  //Recupera con query paginata dalla tabella Products del Northwind 
  //una datatable con gli elementi da start per max
  DataTable products = Products.Retrieve(start, max); 

  DataGrid1.DataSource = products;
  DataGrid1.DataBind();      
 }
 #endregion

 private void Page_Load(object sender, System.EventArgs e)
 {   
  //Non ho necessità di gestire il postback perchè la pagina - per come è fatta - 
  //verrà sempre chiamata in GET.     
  BindDataGrid();
 }

 [Web Form Designer generated code]
}

[pagina aspx]

<%@ Page language="c#" Codebehind="IndexedPaging.aspx.cs" AutoEventWireup="false" Inherits="Paging.IndexedPaging" enableViewState="False"%>
<%@ Register TagPrefix="cc1" Namespace="Paging" Assembly="Paging" %>

<HTML>
<FORM id=Form1 method=post runat="server">
<cc1:PageNavigationControl id=PageNavigationControl1 runat="server"></cc1:PageNavigationControl>
<asp:datagrid id=DataGrid1 runat="server" Width="703px" Height="197px" AllowCustomPaging="True">
<HEADERSTYLE BackColor="#8080FF" ForeColor="White" Font-Bold="True"></HEADERSTYLE>
<PAGERSTYLE Mode="NumericPages" Position="TopAndBottom"></PAGERSTYLE>
</asp:datagrid>
</FORM></HTML>

Questo che propongo non è IL modo ma è UN modo, è interessante - ad esempio - usare la cache invece di usare query paginate (qui un articolo), l'applicazione di questo post dipende dal contesto. Il post vuole essere una base di partenza per provare a indicizzare il proprio sito anche se usando la datagrid.

Ovviamente il post va preso "AS IS" e non conferisce alcun diritto. A differenza di molti altri post che metto sul questo blog questo è da me usato! :-p

«febbraio»
domlunmarmergiovensab
303112345
6789101112
13141516171819
20212223242526
272812345
6789101112