Freigeben über


Geschachtelte Datenwebsteuerelemente (C#)

von Scott Mitchell

PDF herunterladen

In diesem Lernprogramm erfahren Sie, wie Sie einen Repeater verwenden, der in einem anderen Repeater geschachtelt ist. In den Beispielen wird veranschaulicht, wie der innere Repeater sowohl deklarativ als auch programmgesteuert aufgefüllt wird.

Einleitung

Neben statischer HTML- und Datenbindungssyntax können Vorlagen auch Websteuerelemente und Benutzersteuerelemente enthalten. Diese Websteuerelemente können ihre Eigenschaften entweder über deklarative Datenbindungssyntax zugewiesen werden oder programmgesteuert innerhalb der entsprechenden serverseitigen Ereignishandler aufgerufen werden.

Durch das Einbetten von Steuerelementen in eine Vorlage kann das Erscheinungsbild und die Benutzeroberfläche angepasst und verbessert werden. Im Lernprogramm „Verwenden von TemplateFields im GridView-Steuerelement“ haben wir beispielsweise gezeigt, wie Sie die Anzeige des GridView anpassen, indem Sie ein Kalendersteuerelement in einem TemplateField hinzufügen, um das Einstellungsdatum eines Mitarbeiters anzuzeigen. In den Lernprogrammen zum Hinzufügen von Validierungssteuerelementen zu den Bearbeitungs- und Einfügeschnittstellen und zur Anpassung der Schnittstelle für Datenänderungen haben wir gezeigt, wie Sie die Bearbeitungs- und Einfügeschnittstellen anpassen, indem Sie Validierungssteuerelemente, Eingabefelder, Dropdown-Listen und andere Websteuerelemente hinzufügen.

Vorlagen können auch andere Datenwebsteuerelemente enthalten. Das heißt, wir können eine DataList haben, die eine andere DataList (oder Repeater- oder GridView- oder DetailsView usw.) in ihren Template-Vorlagen enthält. Die Herausforderung bei einer solchen Schnittstelle besteht darin, die entsprechenden Daten an das innere Datenwebsteuerelement zu binden. Es gibt ein paar verschiedene Ansätze, angefangen bei deklarativen Optionen mithilfe von ObjectDataSource bis hin zu programmgesteuerten Ansätzen.

In diesem Lernprogramm erfahren Sie, wie Sie einen Repeater verwenden, der in einem anderen Repeater geschachtelt ist. Der äußere Repeater enthält ein Element für jede Kategorie in der Datenbank, wobei der Name und die Beschreibung der Kategorie angezeigt werden. Jeder interne Repeater der Kategorie zeigt Informationen für jedes Produkt an, das zu dieser Kategorie gehört (siehe Abbildung 1) in einer Aufzählung. In unseren Beispielen wird veranschaulicht, wie der innere Repeater sowohl deklarativ als auch programmgesteuert aufgefüllt wird.

Jede Kategorie wird zusammen mit ihren Produkten aufgelistet.

Abbildung 1: Jede Kategorie zusammen mit den zugehörigen Produkten wird aufgelistet (Zum Anzeigen des Bilds mit voller Größe klicken)

Schritt 1: Erstellen der Kategorieauflistung

Beim Erstellen einer Seite, die geschachtelte Datenwebsteuerelemente verwendet, finde ich es hilfreich, zuerst das äußerste Datenwebsteuerelement zu entwerfen, zu erstellen und zu testen, ohne sich gedanken über das innere geschachtelte Steuerelement zu machen. Beginnen wir daher mit den Schritten, die erforderlich sind, um der Seite einen Repeater hinzuzufügen, der den Namen und die Beschreibung für jede Kategorie auflistet.

Öffnen Sie zunächst die NestedControls.aspx Seite im DataListRepeaterBasics Ordner, und fügen Sie der Seite ein Repeater-Steuerelement hinzu, und legen Sie dessen ID Eigenschaft auf CategoryList. Wählen Sie im Smarttag 'Repeater' die Option aus, eine neue ObjectDataSource namens CategoriesDataSource zu erstellen.

Benennen Sie die neue ObjectDataSource CategoriesDataSource

Abbildung 2: Benennen der neuen ObjectDataSource CategoriesDataSource (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Konfigurieren Sie die ObjectDataSource so, dass sie ihre Daten aus der Methode CategoriesBLL der Klasse GetCategories abruft.

Konfigurieren Sie die ObjectDataSource zur Verwendung der GetCategories-Methode der CategoriesBLL-Klasse

Abbildung 3: Konfigurieren der ObjectDataSource für die Verwendung der CategoriesBLL Klassenmethode GetCategories (Klicken, um das Bild in voller Größe anzuzeigen)

Um den Vorlageninhalt des Repeaters anzugeben, müssen wir zur Quellansicht wechseln und die deklarative Syntax manuell eingeben. Fügen Sie ein ItemTemplate hinzu, das den Namen der Kategorie in einem <h4>-Element und die Beschreibung der Kategorie in einem Absatzelement (<p>) darstellt. Darüber hinaus trennen wir jede Kategorie durch eine horizontale Regel (<hr>). Nachdem Sie diese Änderungen vorgenommen haben, sollte Ihre Seite deklarative Syntax für Repeater und ObjectDataSource enthalten, die der folgenden Syntax ähnelt:

<asp:Repeater ID="CategoryList" DataSourceID="CategoriesDataSource"
    EnableViewState="False" runat="server">
    <ItemTemplate>
        <h4><%# Eval("CategoryName") %></h4>
        <p><%# Eval("Description") %></p>
    </ItemTemplate>
    <SeparatorTemplate>
        <hr />
    </SeparatorTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Abbildung 4 zeigt unseren Fortschritt, wenn er über einen Browser angezeigt wird.

Jeder Name und jede Beschreibung der Kategorie wird durch eine horizontale Regel getrennt aufgeführt.

Abbildung 4: Jeder Kategoriename und jede Beschreibung wird aufgelistet, getrennt durch eine horizontale Regel (Klicken, um das Bild in voller Größe anzuzeigen)

Schritt 2: Hinzufügen des geschachtelten Produktwiederholers

Nachdem die Kategorieauflistung abgeschlossen ist, besteht die nächste Aufgabe darin, einen Repeater hinzuzufügen, der Informationen zu den Produkten anzeigt, die zur entsprechenden Kategorie gehören. Es gibt eine Reihe von Möglichkeiten, die Daten für diesen inneren Repeater abzurufen, von denen zwei in Kürze untersucht werden. Lassen Sie uns jetzt einfach die Produkte-Repeater innerhalb des CategoryList Repeaters ItemTemplate erstellen. Spezifisch soll der Produkt-Repeater jedes Produkt in einer Aufzählungsliste anzeigen, wobei jedes Listenelement den Produktnamen und den Preis enthalten soll.

Um diesen Repeater zu erstellen, müssen wir die deklarative Syntax und die Vorlagen des inneren Repeaters manuell in das CategoryListItemTemplate eingeben. Fügen Sie das folgende Markup innerhalb des CategoryList Repeaters ItemTemplate hinzu:

<asp:Repeater ID="ProductsByCategoryList" EnableViewState="False"
    runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><strong><%# Eval("ProductName") %></strong>
            (<%# Eval("UnitPrice", "{0:C}") %>)</li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>

Schritt 3: Bindung der Category-Specific-Produkte an den "ProductsByCategoryList"-Repeater

Wenn Sie die Seite an diesem Punkt über einen Browser besuchen, sieht Ihr Bildschirm wie in Abbildung 4 aus, da wir noch keine Daten an den Repeater binden müssen. Es gibt einige Möglichkeiten, wie wir die entsprechenden Produktdatensätze abrufen und an den Repeater binden können, einige effizienter als andere. Die größte Herausforderung besteht hier darin, die entsprechenden Produkte für die angegebene Kategorie zurückzuholen.

Auf die Daten, die an das innere Repeater-Steuerelement gebunden werden sollen, kann entweder deklarativ über eine ObjectDataSource in den CategoryList Repeater-Steuerelementen ItemTemplate oder programmgesteuert über die Code-Behind-Seite der ASP.NET-Seite zugegriffen werden. Auf ähnliche Weise können diese Daten entweder deklarativ an den inneren Repeater gebunden werden – entweder über die eigenschaft des inneren Repeaters DataSourceID oder durch deklarative Datenbindungssyntax oder programmgesteuert durch Verweisen auf den inneren Repeater im Ereignishandler des CategoryListItemDataBound Repeaters, programmgesteuertes Festlegen der DataSource Eigenschaft und Aufrufen der DataBind() Methode. Lassen Sie uns jeden dieser Ansätze untersuchen.

Deklarativer Zugriff auf die Daten mit einem ObjectDataSource-Steuerelement und demItemDataBoundEreignishandler

Da wir die ObjectDataSource in dieser Lernprogrammreihe umfassend verwendet haben, besteht die natürliche Wahl für den Zugriff auf Daten für dieses Beispiel darin, mit der ObjectDataSource zu bleiben. Die ProductsBLL Klasse verfügt über eine GetProductsByCategoryID(categoryID) Methode, die Informationen zu diesen Produkten zurückgibt, die zum angegebenen Produkt categoryIDgehören. Daher können wir eine ObjectDataSource zum CategoryList Repeater ItemTemplate hinzufügen und sie so konfigurieren, dass sie auf die Daten aus der Methode dieser Klasse zugreift.

Leider lässt der Repeater seine Vorlagen nicht über die Entwurfsansicht bearbeiten, sodass wir die deklarative Syntax für dieses ObjectDataSource-Steuerelement manuell hinzufügen müssen. Die folgende Syntax zeigt den CategoryList Repeater ItemTemplate nach Hinzufügung dieser neuen ObjectDataSource (ProductsByCategoryDataSource):

<h4><%# Eval("CategoryName") %></h4>
<p><%# Eval("Description") %></p>
<asp:Repeater ID="ProductsByCategoryList" EnableViewState="False"
        DataSourceID="ProductsByCategoryDataSource" runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><strong><%# Eval("ProductName") %></strong> -
                sold as <%# Eval("QuantityPerUnit") %> at
                <%# Eval("UnitPrice", "{0:C}") %></li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsByCategoryDataSource" runat="server"
           SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
   <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
   </SelectParameters>
</asp:ObjectDataSource>

Bei Verwendung des ObjectDataSource-Ansatzes müssen wir die ProductsByCategoryList Repeater-Eigenschaft DataSourceID auf die ID ObjectDataSource (ProductsByCategoryDataSource) festlegen. Beachten Sie außerdem, dass unsere ObjectDataSource über ein <asp:Parameter> Element verfügt, das den Wert angibt, der categoryID an die GetProductsByCategoryID(categoryID) Methode übergeben wird. Aber wie geben wir diesen Wert an? Im Idealfall können wir die DefaultValue Eigenschaft des <asp:Parameter> Elements mit der Datenbindungssyntax wie folgt festlegen:

<asp:Parameter Name="CategoryID" Type="Int32"
     DefaultValue='<%# Eval("CategoryID")' />

Leider ist die Datenbindungssyntax nur in Steuerelementen mit einem DataBinding Ereignis gültig. Die Parameter Klasse fehlt ein solches Ereignis und daher ist die obige Syntax unzulässig und führt zu einem Laufzeitfehler.

Um diesen Wert festzulegen, müssen wir einen Ereignishandler für das CategoryList Repeater-Ereignis ItemDataBound erstellen. Erinnern Sie sich daran, dass das ItemDataBound Ereignis einmal für jedes Element ausgelöst wird, das an den Repeater gebunden ist. Jedes Mal, wenn dieses Ereignis für den äußeren Repeater ausgelöst wird, können wir den aktuellen CategoryID Wert dem ProductsByCategoryDataSource ObjectDataSource-Parameter CategoryID zuweisen.

Erstellen Sie einen Ereignishandler für das CategoryList Repeater-Ereignis ItemDataBound mit dem folgenden Code:

protected void CategoryList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.AlternatingItem ||
        e.Item.ItemType == ListItemType.Item)
    {
        // Reference the CategoriesRow object being bound to this RepeaterItem
        Northwind.CategoriesRow category =
            (Northwind.CategoriesRow)((System.Data.DataRowView)e.Item.DataItem).Row;
        // Reference the ProductsByCategoryDataSource ObjectDataSource
        ObjectDataSource ProductsByCategoryDataSource =
            (ObjectDataSource)e.Item.FindControl("ProductsByCategoryDataSource");
        // Set the CategoryID Parameter value
        ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
            category.CategoryID.ToString();
    }
}

Dieser Ereignishandler beginnt damit sicherzustellen, dass wir es mit einem Datenelement und nicht mit einem Kopf-, Fußzeilen- oder Trennzeichenelement zu tun haben. Als Nächstes verweisen wir auf die tatsächliche CategoriesRow Instanz, die gerade an die aktuelle RepeaterItemInstanz gebunden wurde. Schließlich verweisen wir auf die ObjectDataSource in der ItemTemplate und weisen den CategoryID Parameterwert dem CategoryID des aktuellen RepeaterItem zu.

Dieser Ereignishandler bindet den ProductsByCategoryList Repeater in jedem RepeaterItem an die Produkte der Kategorie RepeaterItem. Abbildung 5 zeigt einen Screenshot der resultierenden Ausgabe.

Die äußere Wiederholung listet jede Kategorie auf; die innere Wiederholung listet die Produkte für diese Kategorie auf.

Abbildung 5: Der äußere Wiederholer listet jede Kategorie auf; der innere Wiederholer listet die Produkte für diese Kategorie auf (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Programmgesteuerter Zugriff auf die Produkte nach Kategoriedaten

Anstatt eine ObjectDataSource zum Abrufen der Produkte für die aktuelle Kategorie zu verwenden, könnten wir eine Methode in der CodeBehind-Klasse unserer ASP.NET-Seite (oder im App_Code Ordner oder in einem separaten Klassenbibliotheksprojekt) erstellen, die den entsprechenden Satz von Produkten zurückgibt, wenn sie in einem CategoryID übergeben werden. Stellen Sie sich vor, dass wir eine solche Methode in unserer ASP.NET Code-Behind-Klasse hatten und sie GetProductsInCategory(categoryID) genannt wurde. Mit dieser Methode könnten wir die Produkte für die aktuelle Kategorie mithilfe der folgenden deklarativen Syntax an den inneren Repeater binden:

<asp:Repeater runat="server" ID="ProductsByCategoryList" EnableViewState="False"
      DataSource='<%# GetProductsInCategory((int)(Eval("CategoryID"))) %>'>
  ...
</asp:Repeater>

Die Repeater-Eigenschaft verwendet die Datenbindungssyntax DataSource , um anzugeben, dass ihre Daten aus der GetProductsInCategory(categoryID) Methode stammen. Da Eval("CategoryID") ein Wert vom Typ Object zurückgegeben wird, wandeln wir das Objekt in ein Integer um, bevor es an die GetProductsInCategory(categoryID) Methode übergeben wird. Beachten Sie, dass der CategoryID hier über die Datenbindungssyntax zugegriffene CategoryID der äußere Repeater (CategoryList) ist, der mit den Datensätzen in der Categories Tabelle verknüpft ist. Daher wissen wir, dass CategoryID kein Datenbankwert NULL sein kann, weshalb wir die Eval-Methode ohne weiteres konvertieren können, ohne zu prüfen, ob es sich um ein DBNull handelt.

Mit diesem Ansatz müssen wir die GetProductsInCategory(categoryID)-Methode erstellen und die entsprechenden Produkte auf Grundlage der bereitgestellten categoryID abrufen. Wir können dies tun, indem wir einfach das von der ProductsDataTable Klasse ProductsBLL Methode zurückgegebene GetProductsByCategoryID(categoryID) zurückgeben. Erstellen wir die GetProductsInCategory(categoryID) Methode in der CodeBehind-Klasse für unsere NestedControls.aspx Seite. Verwenden Sie dazu den folgenden Code:

protected Northwind.ProductsDataTable GetProductsInCategory(int categoryID)
{
    // Create an instance of the ProductsBLL class
    ProductsBLL productAPI = new ProductsBLL();
    // Return the products in the category
    return productAPI.GetProductsByCategoryID(categoryID);
}

Diese Methode erstellt einfach eine Instanz der ProductsBLL Methode und gibt die Ergebnisse der GetProductsByCategoryID(categoryID) Methode zurück. Beachten Sie, dass die Methode mit Public oder Protected markiert werden muss; wenn die Methode mit Private markiert ist, kann nicht aus dem deklarativen Markup der ASP.NET-Seite zugegriffen werden.

Nachdem Sie diese Änderungen an dieser neuen Technik vorgenommen haben, nehmen Sie sich einen Moment Zeit, um die Seite über einen Browser anzuzeigen. Die Ausgabe sollte identisch sein wie bei Verwendung des ObjectDataSource-Ansatzes und des ItemDataBound Ereignishandlers (siehe Abbildung 5 für einen Screenshot).

Hinweis

Es mag wie eine unnötige Aufgabe erscheinen, die GetProductsInCategory(categoryID) Methode in der CodeBehind-Klasse der ASP.NET-Seite zu erstellen. Schließlich erstellt diese Methode einfach eine Instanz der ProductsBLL Klasse und gibt die Ergebnisse der GetProductsByCategoryID(categoryID) Methode zurück. Warum rufen Sie diese Methode nicht direkt aus der Datenbindungssyntax im inneren Repeater auf, z. B.: DataSource='<%# ProductsBLL.GetProductsByCategoryID((int)(Eval("CategoryID"))) %>'? Obwohl diese Syntax nicht mit unserer aktuellen Implementierung der ProductsBLL Klasse funktioniert (da die GetProductsByCategoryID(categoryID) Methode eine Instanzmethode ist), können Sie ändern ProductsBLL , um eine statische GetProductsByCategoryID(categoryID) Methode einzuschließen oder die Klasse eine statische Instance() Methode enthält, um eine neue Instanz der ProductsBLL Klasse zurückzugeben.

Während solche Änderungen die Notwendigkeit der GetProductsInCategory(categoryID) Methode in der Code-Behind-Klasse der ASP.NET-Seite beseitigen würden, bietet uns die Code-Behind-Klassenmethode mehr Flexibilität beim Arbeiten mit den abgerufenen Daten, wie wir in Kürze sehen werden.

Gleichzeitiges Abrufen aller Produktinformationen

Die beiden vorherigen Techniken, die wir untersucht haben, greifen diese Produkte für die aktuelle Kategorie durch einen Aufruf der Methode ProductsBLL der Klasse GetProductsByCategoryID(categoryID) (der erste Ansatz hat dies über eine ObjectDataSource getan, der zweite durch die GetProductsInCategory(categoryID) Methode in der Code-Behind-Klasse). Jedes Mal, wenn diese Methode aufgerufen wird, ruft die Geschäftslogikschicht die Datenzugriffsebene auf, die die Datenbank mit einer SQL-Anweisung abfragt, die Zeilen aus der Products Tabelle zurückgibt, deren CategoryID Feld dem angegebenen Eingabeparameter entspricht.

Bei N Kategorien im System führt dieser Ansatz N + 1 Datenbankabfragen aus: Eine Abfrage, um alle Kategorien abzurufen, und anschließend N Abfragen, um die Produkte zu erhalten, die für jede Kategorie spezifisch sind. Wir können jedoch alle erforderlichen Daten in nur zwei Datenbankaufrufen abrufen: einen Anruf, um alle Kategorien zu erhalten, und einen weiteren, um alle Produkte zu erhalten. Sobald wir alle Produkte haben, können wir diese Produkte filtern, sodass nur die Produkte, die dem aktuellen CategoryID entsprechen, an den inneren Repeater dieser Kategorie gebunden sind.

Um diese Funktionalität bereitzustellen, müssen wir nur eine geringfügige Änderung an der GetProductsInCategory(categoryID) Methode in unserer codeBehind-Klasse der ASP.NET Seite vornehmen. Anstatt blind die Ergebnisse der ProductsBLL Klassenmethode GetProductsByCategoryID(categoryID) zurückzugeben, können wir zuerst auf alle Produkte zugreifen (sofern sie noch nicht darauf zugegriffen wurden) und dann nur die gefilterte Ansicht der Produkte basierend auf der übergebenen CategoryIDMethode zurückgeben.

private Northwind.ProductsDataTable allProducts = null;
protected Northwind.ProductsDataTable GetProductsInCategory(int categoryID)
{
    // First, see if we've yet to have accessed all of the product information
    if (allProducts == null)
    {
        ProductsBLL productAPI = new ProductsBLL();
        allProducts = productAPI.GetProducts();
    }
    // Return the filtered view
    allProducts.DefaultView.RowFilter = "CategoryID = " + categoryID;
    return allProducts;
}

Beachten Sie das Hinzufügen der Variablen auf Seitenebene, allProducts. Dies enthält Informationen zu allen Produkten und wird beim ersten Aufrufen der GetProductsInCategory(categoryID) Methode aufgefüllt. Nachdem sichergestellt wurde, dass das allProducts-Objekt erstellt und befüllt wurde, filtert die Methode die Ergebnisse der DataTable so, dass nur auf die Zeilen zugegriffen werden kann, deren CategoryID mit dem angegebenen CategoryID übereinstimmt. Dieser Ansatz reduziert die Anzahl der Zugriffe auf die Datenbank von N + 1 bis zu zwei.

Durch diese Erweiterung werden keine Änderungen am gerenderten Markup der Seite eingeführt, und es werden weniger Datensätze als der andere Ansatz zurückgespielt. Sie reduziert einfach die Anzahl der Aufrufe an die Datenbank.

Hinweis

Ein Grund könnte intuitiv sein, dass die Verringerung der Anzahl der Datenbankzugriffe die Leistung sicher verbessern würde. Dies ist jedoch möglicherweise nicht der Fall. Wenn Sie über eine große Anzahl von Produkten verfügen, deren CategoryID Wert NULLbeispielsweise lautet, gibt der Aufruf der GetProducts Methode eine Reihe von Produkten zurück, die nie angezeigt werden. Darüber hinaus kann es ineffizient sein, alle Produkte zurückzugeben, wenn Sie nur einen Ausschnitt der Kategorien anzeigen, was der Fall sein kann, wenn Sie Paging implementiert haben.

Wie immer, wenn es darum geht, die Leistung von zwei Techniken zu analysieren, besteht die einzige surefire-Maßnahme darin, kontrollierte Tests auszuführen, die auf die gängigen Fallszenarien Ihrer Anwendung zugeschnitten sind.

Zusammenfassung

In diesem Tutorial haben wir gelernt, wie ein Datenkontrollelement in einem anderen geschachtelt werden kann, insbesondere, wie ein äußerer Repeater ein Element für jede Kategorie anzeigt und ein innerer Repeater die Produkte jeder Kategorie in einer Aufzählungsliste auflistet. Die wichtigste Herausforderung beim Erstellen einer geschachtelten Benutzeroberfläche liegt beim Zugreifen auf und Binden der richtigen Daten an das innere Datenwebsteuerelement. Es gibt eine Vielzahl von Techniken, von denen wir zwei in diesem Tutorial untersucht haben. Der erste Untersuchte Ansatz verwendet eine ObjectDataSource in den äußeren Datenwebsteuerelementen ItemTemplate , die über ihre DataSourceID Eigenschaft an das innere Datenwebsteuerelement gebunden wurden. Die zweite Technik hat über eine Methode in der CodeBehind-Klasse der ASP.NET Seite auf die Daten zugegriffen. Diese Methode kann dann über die Datenbindungssyntax an die Eigenschaft des inneren Daten-Websteuerelements DataSource gebunden werden.

Während die in diesem Tutorial untersuchte geschachtelte Benutzeroberfläche einen Repeater verwendet hat, der in einem Repeater geschachtelt ist, können diese Techniken auch auf andere Daten-Web-Steuerelemente erweitert werden. Sie können einen Repeater innerhalb einer GridView oder eine GridView innerhalb einer DataList verschachteln und so weiter.

Glückliche Programmierung!

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.

Besonderer Dank an

Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüfer für dieses Lernprogramm waren Zack Jones und Liz Shulok. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.