Thomas Bandt

Über mich | Kontakt | Archiv

[ASP.NET 2.0] Verschachtelte Repeater

Folgendes Szenario: Man möchte eine einfache Linkliste erstellen, die stur von oben nach unten erstellt wird - die Inhalte möchte man aber nicht von Hand pflegen sondern irgendwo speichern (Datenbank, XML). Dabei sollen die einzelnen Einträge in Kategorien gruppiert werden können.

Technisch gesehen braucht man hierfür also zwei Schleifen: eine äußere für die Kategorien, und eine innere für die einzelnen Einträge jeder Kategorie. In ASP.NET gibt es hierfür ja wunderbare fertige Controls, d.h. die Schleifen muss man nicht selbst programmieren.

Für diesen Fall drängt sich das Repeater-Control auf, was im Markup dann wie folgt deklariert wird:

"RCategories" runat="server"
OnItemDataBound="BindItems">
   
      

<%# Eval("Name") %>


      "RItems" runat="server">
         
            

             
             
                   
  • <%# Eval("Name") %>
             
             
                

         
      
 
   

Was steht hier geschrieben? Nun zuerst sollte auffallen, dass hier zwei Repeater-Controls verschachtelt sind. Man kann also innerhalb des Item-Templates des ersten Repeaters, auch einen zweiten (und so weiter ...) platzieren. Im ersten Item-Template wird zudem vorher noch die Kategorie-Bezeichnung als Überschrift 4. Ordnung ausgegeben.

Innerhalb des Repeaters für die Einträge generieren wir eine HTML-Liste. Praktischerweise sollte hier HeaderTemplate und FooterTemplate für das öffnende und das schließende Listen-Tag verwendet werden, der Vorteil: hat man keine Items in der Liste, werden die zwei Tags auch nicht angezeigt, man spart sich also manuelles ein- und ausblenden, was nötig wäre, würde man die Tags außerhalb des Repeaters platzieren.

Außerdem wurde eine Methode definiert, die zum Event "On Item Bound", also wenn der erste Repeater mit Daten befüllt wurde, greift. Dazu gleich mehr.

Ersteinmal noch ein Wort zu den Daten, die ich binde: das sind in diesem Fall eigene Objekte, die man in der Praxis mit beliebigen Eigenschaften ausstatten kann. Für dieses Beispiel reicht jeweils eine Eigenschaft "Name" sowie für die Einträge noch eine vom Typ "CategoryID", um eine Verknüpfung zur Kategorie herstellen zu können.

Das Befüllen übernehme ich ausnahmsweise von Hand, in der Praxis wird das wohl in nem Data-Access-Layer gegen eine Datenbank oder andere Datenquelle geschehen:

private List _Items;
private List _Categories;

protected override void OnInit(EventArgs e)
{
   base.OnInit(e);

   _Items = new List();
   _Categories = new List();

   // Kategorien füllen
   _Categories.Add(new Category(1, "Kategorie 1"));
   _Categories.Add(new Category(2, "Kategorie 2 TEST"));

   // Items hinzufügen
   _Items.Add(new Item(1, "hallo welt"));
   _Items.Add(new Item(1, "noch eine"));
   _Items.Add(new Item(2, "Item der 2. Kategorie"));

}

Nun binden wir die Kategorien an den äußeren Repeater:

protected void Page_Load(object sender, EventArgs e)
{
   RCategories.DataSource = _Categories;
   RCategories.DataBind();
}

Nach diesem DataBind greift automatisch das oben angesprochene Event "OnItemDataBound". Hier können wir nun den inneren Repeater mit Daten füttern:

protected void BindItems(object sender, RepeaterItemEventArgs e)
{
   Category cat = (Category)e.Item.DataItem;
   Repeater RItems = (Repeater)e.Item.FindControl("RItems");

   RItems.DataSource = GetItemsPerCategory(cat.ID);
   RItems.DataBind();
}

Der springende Punkt hier: e.Item.DataItem entspricht dem "ursprünglichen Objekt", d.h. wenn wir hier auf den Typ Category casten, dann erhalten wir unser ursprüngliches Objekt mit allen Daten von oben wieder, für die erste Kategorie wäre das "Kategorie 1" mit der ID 1.

Um den Repeater "zu bekommen", holen wir ihn uns über FindControl(). Anschließend binden wir dann die zu dieser Kategorie passenden Items an diesen Repeater.

Und siehe da, die Ausgabe passt:

ToDo:

By the way: man kann das Ganze sicher auch alles im über ObjectDataSource & Co erledigen - allerdings ist das nicht der Weg, den ich bevorzuge. Ich halte nicht viel von dem ganzen Klickibunti-Zeug. Zwar kann man damit sehr schnell zum Ziel kommen, wenn die Aufgaben einfach gestrickt sind, und die Wiederverwendbarkeit und Wartbarkeit des Codes keine Rolle spielt, aber in den meisten Fällen lohnt sich der vermeintliche "Mehraufwand", den man hat, wenn man es "von Hand" macht, dann doch. Letztendlich führen aber wie immer viele Wege nach Rom.

Download:

Das Sample steht hier als lauffähige Beispielanwendung zur Verfügung:

VerschachtelteRepeater.zip (3,39 KB)

Kommentare

  1. Hannes Preishuber schrieb am Montag, 2. Oktober 2006 13:03:00 Uhr:

    wers gerne Codefrei haben möchte
    http://www.devtrain.de/news.aspx?artnr=961

  2. Achim Zeeck schrieb am Freitag, 17. November 2006 08:50:00 Uhr:

    Sowas geht auch mit Sitemaps (per XML) komfortabel. Die Elemente lassen sich zusätzlich auch in Ressourcendateien ablegen - außerdem können diese auch gleich mehrsprachig designed werden ([link].sitemap.[country].resx, z.B. Menu.sitemap -> Menu.sitemap.resx usw.)


« Zurück  |  Weiter »