Entwickeln eines datengebundenen Steuerelements mit Vorlagen
Das Binden einer Eigenschaft eines Steuerelements an ein einzelnes Datenelement (oder einen einzelnen Ausdruck) ist mit Hilfe der ASP.NET-Datenbindungssyntax leicht auszuführen. Dieser Abschnitt beschäftigt sich mit dem komplexeren Szenario der Entwicklung eines Steuerelements, das an die Datenquelle gebundene vorlagenbasierte Eigenschaften besitzt, wobei die Datenquelle ein Auflistungstyp (System.Collections.ICollection oder System.Collections.IEnumerable) ist. Mit Hilfe von Vorlagen ist es bei der Seitenentwicklung möglich, die Präsentation von mit dem Steuerelement verbundenen Daten anzupassen. Die Steuerelemente Repeater und DataList sind Beispiele für aus Vorlagen gebildete datengebundene Steuerelemente.
Einen Überblick über Datenbindung auf ASP.NET-Seiten finden Sie unter Schnelleinstieg zu ASP.NET —> ASP.NET Web Forms —> Datenbindung von Serversteuerelementen. Hintergrundinformationen zum Erstellen aus Vorlagen gebildeter Steuerelemente finden Sie unter Entwickeln eines Steuerelements mit Vorlagen.
Ein vorlagenbasiertes datengebundenes Steuerelement besitzt eine Datenquelleneigenschaft vom Typ ICollection oder IEnumerable und eine oder mehrere Eigenschaften vom Typ ITemplate. Der Container für eine der Vorlageneigenschaften definiert eine Eigenschaft (in der Regel mit der Bezeichnung DataItem
) zur Datenbindung. Das Steuerelement implementiert seine datenbindende Logik in der Databind-Methode, die es von Control geerbt hat. Die CreateChildControls-Methode wird außer Kraft gesetzt, um die Hierarchie der untergeordneten Steuerelemente beim Rücksenden neu zu erstellen. Diese Schritte werden im Folgenden detailliert besprochen.
So entwickeln Sie ein vorlagenbasiertes datengebundenes Steuerelement
Definieren Sie ein Steuerelement, das die System.Web.UI.INamingContainer-Schnittstelle implementiert.
public class TemplatedList : WebControl, INamingContainer {...} [Visual Basic] Public Class TemplatedList Inherits WebControl Implements INamingContainer ... End Class
Definieren Sie eine Eigenschaft vom Typ System.Web.UI.ITemplate.
[TemplateContainer(typeof(TemplatedListItem))] public virtual ITemplate ItemTemplate { get { return itemTemplate; } set { itemTemplate = value; } } [Visual Basic] <TemplateContainer(GetType(TemplatedListItem))> _ Public Overridable Property ItemTemplate() As ITemplate Get Return _itemTemplate End Get Set _itemTemplate = value End Set End Property
Der logische Container für die Vorlage (angegeben im TemplateContainerAttribute-Attribut) muss eine Eigenschaft zum Binden von Daten besitzen. In der Regel wird diese Eigenschaft als DataItem bezeichnet. Einzelheiten zu logischen Containern für Vorlageneigenschaften finden Sie unter Entwickeln eines Steuerelements mit Vorlagen. Im folgenden Beispiel wird ein Container für die Vorlageneigenschaft definiert.
public class TemplatedListItem : TableRow, INamingContainer { private object dataItem; public virtual object DataItem { get { return dataItem; } set { dataItem = value; } } [Visual Basic] Public Class TemplatedListItem Inherits TableRow Implements INamingContainer Private _dataItem As Object Public Overridable Property DataItem() As Object Get Return _dataItem End Get Set _dataItem = value End Set End Property End Class
Setzen Sie die DataBind-Methode (von Control geerbt) außer Kraft, um die Datenbindungslogik bereitzustellen. Dazu sind die folgenden Schritte notwendig:
- Rufen Sie die OnDataBinding-Methode der Basisklasse auf, um die Handler (von der Seite angefügt) aufzurufen, die die Datenbindungsausdrücke für das Steuerelement auswerten.
- Löschen Sie die Controls-Auflistung.
- Löschen Sie ViewState für die untergeordneten Steuerelemente.
- Erstellen Sie die untergeordneten Steuerelemente mit Hilfe der Datenquelle.
- Weisen Sie das ASP.NET-Seitenframework an, ViewState für das Steuerelement zu überwachen.
Der folgende Code führt diese Schritte aus.
CreateChildControlsHierarchy
ist eine Hilfsmethode zur eigentlichen Erstellung der untergeordneten Steuerelemente. Einzelheiten finden Sie unter Schritt 5.public override void DataBind() { // Controls with a data-source property perform their // custom data binding by overriding DataBind to // evaluate any data-binding expressions on the control // itself. base.OnDataBinding(EventArgs.Empty); // Reset the control's state. Controls.Clear(); ClearChildViewState(); // Create the control hierarchy using the data source. CreateControlHierarchy(true); ChildControlsCreated = true; TrackViewState(); } [Visual Basic] Public Overrides Sub DataBind() ' Controls with a data-source property perform their custom data ' binding by overriding DataBind. ' Evaluate any data-binding expressions on the control itself. MyBase.OnDataBinding(EventArgs.Empty) ' Reset the control state. Controls.Clear() ClearChildViewState() ' Create the control hierarchy using the data source. CreateControlHierarchy(True) ChildControlsCreated = True TrackViewState() End Sub
Setzen Sie CreateChildControls außer Kraft, um die untergeordneten Steuerelemente in einem Rücksendeszenario neu zu erstellen. Dazu gehört das Löschen der Controls-Auflistung und das Erstellen der Steuerelementhierarchie mit Hilfe des Anzeigestatus anstatt der Datenquelle. Das eigentliche Erstellen der untergeordneten Steuerelemente ist in der
CreateControlHierarchy
-Methode verborgen (beschrieben in Schritt 5).protected override void CreateChildControls() { Controls.Clear(); if (ViewState["ItemCount"] != null) { // Create the control hierarchy using the view state, // not the data source. CreateControlHierarchy(false); } } [Visual Basic] Protected Overrides Sub CreateChildControls() Controls.Clear() If Not (ViewState("ItemCount") Is Nothing) Then ' Create the control hierarchy using the view state, ' not the data source. CreateControlHierarchy(False) End If End Sub
Definieren Sie eine Datenquelle, die NULL-Elemente besitzt, und verwenden Sie diese Datenquelle anstatt der eigentlichen Datenquelle zur Erstellung der Steuerelementhierarchie beim Rücksenden. Die Schritte 3 und 4 erstellen die Steuerelementhierarchie mit Hilfe der Datenquelle bzw. des gespeicherten Anzeigestatus. Eine leere Datenquelle ermöglicht einem Steuerelement die Implementierung eines einzelnen Codepfades für die allgemeinen Elemente dieser zwei Schritte.
Hinweis Dieser Schritt (Schritt 5) beschreibt Details der Implementierung, wie sie von den datengebundenen ASP.NET-Steuerelementen in .NET Framework verwendet werden. Die im folgenden Fragment gezeigte
DummyDataSource
-Klasse undCreateControlHierarchy
-Methode sind nicht Teil von .NET Framework, sondern müssen bei der Steuerelemententwicklung definiert werden. Sie müssen diese Elemente nicht implementieren. Es ist jedoch empfehlenswert, dass Sie diese oder eine ähnliche Technik verwenden, um einen allgemeinen Codepfad zur Erstellung der Steuerelementhierarchie anzugeben.Das folgende Codefragment definiert eine leere Datenquelle.
internal sealed class DummyDataSource : ICollection { private int dataItemCount; public DummyDataSource(int dataItemCount) { this.dataItemCount = dataItemCount; } // Implement other methods of the ICollection interface. ... public IEnumerator GetEnumerator() { return new DummyDataSourceEnumerator(dataItemCount); } private class DummyDataSourceEnumerator : IEnumerator { private int count; private int index; public DummyDataSourceEnumerator(int count) { this.count = count; this.index = -1; } public object Current { get { return null; } } // Define other methods of the IEnumerator interface. } } [Visual Basic] NotInheritable Friend Class DummyDataSource Implements ICollection Private dataItemCount As Integer Public Sub New(dataItemCount As Integer) Me.dataItemCount = dataItemCount End Sub ' Implement other methods of the ICollection interface. ... Public Function GetEnumerator() As IEnumerator Implements ICollection.GetEnumerator Return New DummyDataSourceEnumerator(dataItemCount) End Function Private Class DummyDataSourceEnumerator Implements IEnumerator Private count As Integer Private index As Integer Public Sub New(count As Integer) Me.count = count Me.index = - 1 End Sub Public ReadOnly Property Current() As Object Implements IEnumerator.Current Get Return Nothing End Get End Property ' Define other methods of the IEnumerator interface. ... End Class End Class
DummyDataSource
kann wie folgt zur Definition einerCreateControlHierarchy
-Methode verwendet werden.private void CreateControlHierarchy(bool useDataSource) { IEnumerable dataSource = null; int count = -1; if (useDataSource == false) { // ViewState must have a non-null value for ItemCount because this is checked // by CreateChildControls. count = (int)ViewState["ItemCount"]; if (count != -1) { dataSource = new DummyDataSource(count); } } else { dataSource = this.dataSource; } if (dataSource != null) { int index = 0; count = 0; foreach (object dataItem in dataSource) { ... // Invoke a private helper method to create each item. CreateItem(...); count++; index++; } } if (useDataSource) { // Save the number of items contained for use in round trips. ViewState["ItemCount"] = ((dataSource != null) ? count : -1); } } [Visual Basic] Private Sub CreateControlHierarchy(useDataSource As Boolean) Dim dataSource As IEnumerable = Nothing Dim count As Integer = - 1 If useDataSource = False Then ' ViewState must have a non-null value for ItemCount because this is checked ' by CreateChildControls. count = CInt(ViewState("ItemCount")) If count <> - 1 Then dataSource = New DummyDataSource(count) End If Else dataSource = Me._dataSource End If If Not (dataSource Is Nothing) Then Dim table As New Table() Controls.Add(table) Dim selectedItemIndex As Integer = SelectedIndex Dim index As Integer = 0 count = 0 Dim dataItem As Object For Each dataItem In dataSource Dim itemType As ListItemType = ListItemType.Item If index = selectedItemIndex Then itemType = ListItemType.SelectedItem Else If index Mod 2 <> 0 Then itemType = ListItemType.AlternatingItem End If End If CreateItem(table, index, itemType, useDataSource, dataItem) count += 1 index += 1 Next dataItem End If If useDataSource Then ' Save the number of items contained for use in round trips. If Not (dataSource Is Nothing) Then ViewState("ItemCount") = count Else ViewState("ItemCount") = -1 End If End If End Sub
Das eigentliche Erstellen der Vorlage und das Binden der
DataItem
-Eigenschaft an die Datenquelle erfolgt durch dieCreateItem
-Methode. Das folgende Codefragment zeigt, wie dieCreateItem
-Methode in Beispiel für ein datengebundenes Steuerelement mit Vorlagen implementiert wird. Beachten Sie, dass dieCreateItem
-Methode ein Implementierungsdetail und in .NET Framework nicht definiert ist.private TemplatedListItem CreateItem(Table table, int itemIndex, ListItemType itemType, bool dataBind, object dataItem) { TemplatedListItem item = new TemplatedListItem(itemIndex, itemType); TemplatedListItemEventArgs e = new TemplatedListItemEventArgs(item); if (itemTemplate != null) { itemTemplate.InstantiateIn(item.Cells[0]); } if (dataBind) { item.DataItem = dataItem; } OnItemCreated(e); table.Rows.Add(item); if (dataBind) { item.DataBind(); OnItemDataBound(e); item.DataItem = null; } return item; } [Visual Basic] Private Function CreateItem(table As Table, itemIndex As Integer, itemType As ListItemType, dataBind As Boolean, dataItem As Object) As TemplatedListItem Dim item As New TemplatedListItem(itemIndex, itemType) Dim e As New TemplatedListItemEventArgs(item) If Not (_itemTemplate Is Nothing) Then _itemTemplate.InstantiateIn(item.Cells(0)) End If If dataBind Then item.DataItem = dataItem End If OnItemCreated(e) table.Rows.Add(item) If dataBind Then item.DataBind() OnItemDataBound(e) item.DataItem = Nothing End If Return item End Function
Ein Beispiel für ein datengebundenes Steuerelement, das die in diesem Thema erläuterten Schritte implementiert, finden Sie unter Beispiel für eine datengebundenes Steuerelement mit Vorlagen.