Thomas Bandt

Über mich | Kontakt | Archiv

Ein simpler Pager im Eigenbau

Das Problem

ASP.NET bietet wirklich eine Menge netter Features, und auch ans Paging haben die Entwickler von Microsoft gedacht. Die Einsatzmöglichkeiten sind zwar sehr vielfältig, allerdings immer mehr oder weniger an die Listendarstellung innerhalb des Webforms gebunden – unter anderem beim DataGrid. Des Weiteren gibt es von Hause aus keine Möglichkeit, beim Rendern auf das lästige JavaScript und die Roundtrips zum Server zu verzichten. Das heißt zum Einen, dass es ohne JavaScript kein Paging gibt und zum anderen auch, dass man die URL zur zum Beispiel nächsten Seite nicht beeinflussen kann.

Genau das habe ich jedoch benötigt. Denn was nützt mir die beste Suchmaschinenoptimierung samt URL-Rewriting, wenn der Spider beim Pager aussteigt? Nichts. Desweiteren habe ich für meine Anwendung keine direkte Ausgabe im Webform benötigt – ich wollte lediglich eine Schleife laufen (und in dieser dynamisch geladene UserControls an einen Placeholder anfügen).

Die Lösung

Der erste Gedanke ging zum DataReader. Der ist schnell, flexibel und verhält sich in etwa so wie das gute alte ADO-Recordset (vom Ansprechverhalten). Allerdings bietet er keinerlei Möglichkeit ohne eine separate Abfrage die Anzahl der per Select geholten Datensätze zu ermitteln. Somit scheidet er aus.

Viel mehr bleibt ja nun nicht mehr übrig, und die Wahl viel – wie sollte es auch anders sein – auf das DataSet. Böse Zungen behaupten zwar, dieses sei nicht ganz so performant, aber für meine Zwecke reichte es in jedem Fall aus. Zumal eine Optimierung per Caching ja auch noch möglich ist – was aber in dem Moment nicht so wichtig war.

Aber nun zur eigentlichen Lösung. Als erstes öffnen wir wie gehabt die Verbindung zur Datenbank, erstellen das DataSet und deklarieren alle benötigten Variablen.

oConn.Open();
DataSet ds = new DataSet();

string CurrentTemplate;
int CurrentID;
int PageSize;
int EndRecord;
int StartRecord;
int RecordCount;
int CurrentPage;

Nachdem wir es gefüllt haben, ermitteln wir den Recordcount, d.h. die tatsächlich enthaltenen Datensätze.

OleDbDataAdapter ad = new OleDbDataAdapter(new OleDbCommand("Select * From Table",oConn));
ad.Fill(ds, "table");
RecordCount = ds.Tables[0].Rows.Count;

Nun deklarieren wir die Anzahl der darzustellenden Datensätze pro Seite. Dieser Wert kann selbstverständlich auch dynamisch vergeben werden – ich hole ihn mir z.B. aus der Web.Config.

int PageSize = 5;

Im nächsten Schritt bestimmen wir die aktuelle Seite, die ich in diesem Fall per QueryString "pg" übergebe.

if(Request.QueryString["pg"] != null && Request.QueryString["pg"] != "") {
if(Request.QueryString["pg"] != "0") {
CurrentPage = int.Parse(Request.QueryString["pg"]) - 1;
}
else {
CurrentPage = 0;
}
}
else {
CurrentPage = 0;
}

Nun geht es an das Ermitteln der darzustellenden Datensätze. Denn Wenn es zum Beispiel nur 65 gibt, wir aber 10 pro Seite anzeigen, dann dürfen auf der 6. Seite auch nur 5 dargestellt werden.

if(CurrentPage*PageSize < RecordCount) {
StartRecord = CurrentPage*PageSize;
if(StartRecord+PageSize-1 < RecordCount) {
EndRecord = StartRecord + PageSize - 1;
}
else {
EndRecord = StartRecord + (RecordCount-StartRecord) - 1;
}
}
else {
StartRecord = 0;
EndRecord = PageSize - 1;
}

Jetzt kommt der kurze Hauptteil, die Schleife in der die Datensätze dargestellt - oder wie in meinem Fall zum Beispiel, die Usercontrols dynamisch geladen und an einen Placeholder gehängt werden.

for(int i=StartRecord; i<=EndRecord; i++) {
}

Um die Datensätze in dieser schleife darzustellen, muss man die einzelnen Felder per Index ansprechen.

Response.Write(ds.Tables[0].Rows[i].ItemArray.GetValue(5).ToString());

Wobei zum Beispiel der Index „5“ in diesem Fall für das 6. Feld bzw. die 6. Spalte des Datensatzes steht. Das bequeme Ansprechen per Feldbezeichner (z.B. „id“) wie beim DataReader steht uns leider im DataSet – bzw. der DataTable - nicht zur Verfügung.

Wo nun das alles erledigt ist, bleibt die Darstellung des eigentlichen Pagers. Dabei sind der Fantasie keine Grenzen gesetzt, sowohl was die Funktionalität als auch das Design und die Platzierung anbelangt. Ich habe mich aufgrund der Projektanforderungen für ein simples „Weiter“ und „Zurück“ entschieden, was ich ebenfalls in UserControls ausgelagert am Ende dynamisch an die eigentlichen Inhalte am Placeholder anhänge.



« Zurück  |  Weiter »