Share via


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

  1. 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
    
  2. 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
    
  3. Setzen Sie die DataBind-Methode (von Control geerbt) außer Kraft, um die Datenbindungslogik bereitzustellen. Dazu sind die folgenden Schritte notwendig:

    1. 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.
    2. Löschen Sie die Controls-Auflistung.
    3. Löschen Sie ViewState für die untergeordneten Steuerelemente.
    4. Erstellen Sie die untergeordneten Steuerelemente mit Hilfe der Datenquelle.
    5. 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
    
  4. 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
    
  5. 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 und CreateControlHierarchy-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 einer CreateControlHierarchy-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 die CreateItem-Methode. Das folgende Codefragment zeigt, wie die CreateItem-Methode in Beispiel für ein datengebundenes Steuerelement mit Vorlagen implementiert wird. Beachten Sie, dass die CreateItem-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.

Siehe auch

Beispiel für ein datengebundenes Steuerelement mit Vorlagen