Thomas Bandt

Über mich | Kontakt | Archiv

Paging im GridView-Control ohne Postbacks

Das neue GridView-Control in ASP.NET 2.0 ist eine echte Bereicherung: viele Funktionen wie Paging, Sortierung usw. die man zuvor zumindest noch teilweise selbst schreiben musste, erledigt es jetzt voll automatisch. Insbesondere beim Paging bleibt fast kein Wunsch offen. Fast.

Zwei Sachen nervten mich dann aber doch:

  1. Postbacks. Im Intranet oder bei für Suchmaschinen nicht relevanten Sachen kein Problem, stellen sie doch im WWW eine unüberwindbare Hürde für Suchmaschinenbots dar, denn: diese schicken keine Formulare ab, noch führen sie (überwiegend zumindest) JavaScript aus. Folge: mehr als Seite 1 wird so kein Bot zu sehen bekommen - die Inhalte werden also nicht indiziert und bleiben dem potenziellen Besucher verborgen.
  2. Der Seperator. Oft möchte man zum Beispiel zwischen "weiter" und "zurück" einen Trenner einfügen - das geht mit den hauseigenen Mitteln des GridView-Controls nicht, bzw. nur mit einem Kompromiss: man kann das Seperator-Zeichen einem der beiden Links, also Vor- und Zurück hinzufügen, oder eben gar nicht. Eine Kleinigkeit, die schnell nerven kann.

Also habe ich mich mal hingesetzt, und geschaut wie aufwändig es ist, Abhilfe zu schaffen. Erstaunlicherweise war es gar nicht aufwändig, da das Control alle benötigten Events und Eigenschaften bereithält, um selbst Hand anzulegen.

Das Original

Hier der Code für ein originales GridView-Control, was sämtliche der gewünschten Aufgaben erledigt:

"GridView1" runat="server" AllowPaging="True" AutoGenerateColumns="False"
   DataKeyNames="ContactId" DataSourceID="AccessDataSource1" PageSize="3">
   
      "ContactId" HeaderText="ContactId" ReadOnly="True" SortExpression="ContactId" />
      "ContactName" HeaderText="ContactName" SortExpression="ContactName" />
   

   "NextPrevious" NextPageText="Weiter" PreviousPageText="Zurck" />

Es ist kein weiterer Code nötig - das Control erledigt alle Aufgaben vollautomatisch.

Die erweiterte Variante

"GridView1" runat="server" AllowPaging="True" AutoGenerateColumns="False"
   DataKeyNames="ContactId" PageSize="3" OnDataBound="SetGridViewPager" DataSourceID="AccessDataSource1">
   
      "ContactId" HeaderText="ContactId" ReadOnly="True" SortExpression="ContactId" />
      "ContactName" HeaderText="ContactName" SortExpression="ContactName" />
   

   "Bottom" />
   
      "PagerPrev" runat="server" Visible="false">Zurck
      "PagerSeperator" runat="server" Visible="false"> |
      "PagerNext" runat="server" Visible="false">Weiter
   

Im Markup kommen jetzt ein paar wesentliche Änderungen hinzu:

Und last but not least der "Code behind":

protected void SetGridViewPager(object sender, EventArgs e)
{

   int page;

   if (!int.TryParse(Request.QueryString["Page"], out page))
      page = 0;
   else
      if (page < 0)
         page = 0;
      else
         page--;

   GridView1.PageIndex = page;

   int total = GridView1.PageCount;
   int current = page + 1;

   if (current + 1 <= total)
   {
      HyperLink PagerNext = (HyperLink)GridView1.BottomPagerRow.FindControl("PagerNext");
      PagerNext.Visible = true;
      PagerNext.NavigateUrl = string.Format("{0}?Page={1}", Request.Path, current + 1);
   }

   if (current - 1 > 0)
   {
      HyperLink PagerPrev = (HyperLink)GridView1.BottomPagerRow.FindControl("PagerPrev");
      PagerPrev.Visible = true;
      PagerPrev.NavigateUrl = string.Format("{0}?Page={1}", Request.Path, current - 1);
   }

   if (current - 1 > 0 && current + 1 <= total)
   {
      Label PagerSeperator = (Label)GridView1.BottomPagerRow.FindControl("PagerSeperator");
      PagerSeperator.Visible = true;
   }

}

Was passiert hier? Der Reihe nach:

  1. Als erstes holen wir uns die Nummer der aktuell darzustellenden Seite im Grid und ziehen 1 ab, um den Index (beginnend bei 0) zu erhalten.
  2. Diesen Index (page) weisen wir dem GridView-Control zu.
  3. Jetzt holen wir uns noch die Anzahl der gesamten Seiten. Diese steht uns hier bereits zur Verfügung, da das Ganze "on item data bound" stattfindet, also nachdem die Daten bereits den Weg ins Grid gefunden haben. Das ist wichtig, da man sonst - führte man das an anderer Stelle aus - DataBind() selbst aufrufen müsste, was aber u.U. zu unnötigen Performance-Einbrüchen führen würde.
  4. Der Rest ist simpel: es wird geprüft, ob die jeweiligen Fälle zum Darstellen der einzelnen Buttons und des Seperators eintreffen, wenn ja werden die Controls sichtbar gesetzt und gefüllt.

Das Beispiel ist absichtlich sehr simpel gehalten. So wird hier zum Navigieren immer der Pfad zur aktuellen Datei genommen, und mit ?Page=X verknüpft. In der Praxis muss natürlich auf weitere Querystrings usw. Rücksicht genommen werden, aber das bleibt jedem selbst überlassen, was und wie er es implementiert.

Das Beispielprojekt steht übrigens hier noch zum Download zur Verfügung (ASP.NET 2.0 Beta 2):

GridviewPaging.zip (15,69 KB)

Update: Sicherheitscheck, ob Seite überhaupt vorhanden ...



« Zurück  |  Weiter »