Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
von Scott Mitchell
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.
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.
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.
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.
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 CategoryList
ItemTemplate
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 CategoryList
ItemDataBound
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 demItemDataBound
Ereignishandler
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 categoryID
gehö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 RepeaterItem
Instanz 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.
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 CategoryID
Methode 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 NULL
beispielsweise 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.