Gewusst wie: Dynamisches Erstellen von Vorlagen für ASP.NET-Webserversteuerelemente

Aktualisiert: November 2007

Bei der Verwendung von auf Vorlagen basierenden Steuerelementen kann möglicherweise erst zur Laufzeit festgestellt werden, welche Vorlagen erforderlich sind bzw. welchen Text oder welche Steuerelemente die Vorlage enthalten soll. In diesem Fall können Sie die Vorlagen dynamisch im Code erstellen.

Hinweis:

Sie können Vorlagen auch als Benutzersteuerelemente erstellen und diese dynamisch an die Steuerelemente der Seite binden. Ausführliche Informationen finden Sie unter Gewusst wie: Erstellen von vorlagenbasierten ASP.NET-Benutzersteuerelementen.

Sie können Vorlagen im Quellcode für alle Steuerelemente erstellen, die Vorlagen verwenden, darunter: DataList, Repeater, GridView, FormView und DetailsView. Im Gegensatz zu den Vorlagen mit Zeilenlayout bei den anderen Steuerelementen verwenden Sie für das GridView-Steuerelement Vorlagen zum Definieren von Spalten.

Hinweis:

Bei der Erstellung von Vorlagenspalten für das GridView-Steuerelement sind im Vergleich zu anderen auf Vorlagen basierenden Steuerelementen einige Unterschiede zu beachten. Ausführliche Informationen finden Sie unter Erstellen einer benutzerdefinierten Spalte in einem GridView-Webserversteuerelement.

Erstellen der Vorlagenklasse

Zum Erstellen dynamischer Vorlagen erstellen Sie eine Vorlagenklasse, die bei Bedarf instanziiert werden kann.

So erstellen Sie eine Vorlagenklasse

  1. Erstellen Sie eine neue Klasse, die die System.Web.UI.ITemplate-Schnittstelle implementiert.

  2. Übergeben Sie optional einen Wert an den Klassenkonstruktor, anhand dessen die Klasse den zu erstellenden Vorlagentyp bestimmen kann (ItemTemplate, AlternatingItemTemplate usw.).

    Hinweis:

    Sie können den Vorlagentyp auf eine typsichere Weise an den Konstruktor übergeben, indem Sie dem Konstruktor einen Parameter des Typs ListItemType hinzufügen. In der ListItemType-Enumeration werden die möglichen Vorlagentypen für das Repeater-Listensteuerelement, das DataList-Listensteuerelement und andere Listensteuerelemente festgelegt.

  3. Implementieren Sie in der Klasse die InstantiateIn-Methode, die ein Member der ITemplate-Schnittstelle ist.

    Diese Methode bietet die Möglichkeit, dem angegebenen Container Instanzen des Textes und der Steuerelemente hinzuzufügen.

  4. Erstellen Sie die Steuerelemente für das Vorlagenelement in der InstantiateIn-Methode, legen Sie deren Eigenschaften fest, und fügen Sie sie anschließend der übergeordneten Controls-Auflistung hinzu.

    Mithilfe des an die InstantiateIn-Methode übergebenen Verweises können Sie auf das übergeordnete Steuerelement zugreifen.

    Hinweis:

    Es ist nicht möglich, der Controls-Auflistung statischen Text direkt hinzuzufügen. Sie können jedoch ein Steuerelement erstellen (beispielsweise ein Literal-Steuerelement oder ein LiteralControl-Steuerelement), dessen Text-Eigenschaft festlegen und dieses Steuerelement dann der übergeordneten Auflistung hinzufügen.

  5. Für Steuerelemente, die Datenbindung erfordern, erstellen und binden Sie eine Methode zur Behandlung des DataBinding-Ereignisses des Steuerelements. Dieses Ereignis wird ausgelöst, wenn das Vorlagenelement mit sämtlichen Steuerelementen erzeugt wurde, und es bietet Ihnen die Möglichkeit, die Daten abzurufen und in einem Steuerelement zu verwenden.

    Hinweis:

    Beim Erstellen von Steuerelementen in der Vorlage kann ein Datenbindungsausdruck nicht als Zeichenfolge eingebettet werden wie es beim Definieren von Vorlagen zur Entwurfszeit möglich ist. Das liegt daran, dass Datenbindungsausdrücke in Code konvertiert werden, bevor die Vorlage erstellt wird.

    Im Handler für das DataBinding-Ereignis können Sie die Inhalte des Steuerelements bearbeiten. Üblicherweise (aber nicht zwangsläufig) rufen Sie die Daten ab und weisen sie der Text-Eigenschaft (oder einer anderen Eigenschaft) des Steuerelements zu.

    Hinweis:

    Weitere Informationen zur Datenbindung in ASP.NET-Webseiten finden Sie unter Zugreifen auf Daten mit ASP.NET.

    Um einer dynamischen Vorlage die Datenbindung hinzuzufügen, führen Sie die folgenden Schritte aus:

    • Fügen Sie einen Ereignishandler für die Datenbindung zu den in der Vorlage erstellten Steuerelementen hinzu.

    • Erstellen Sie den Handler, mit dem Sie die Bindung herstellen möchten. Wählen Sie im Handler die zu bindenden Daten, und weisen Sie sie der entsprechenden Eigenschaft des Steuerelements zu.

      Hinweis:

      Wenn in Ihren Vorlagen verschiedene Steuerelementtypen vorhanden sind, müssen Sie für jeden Typ einen anderen Datenbindungs-Ereignishandler erstellen.

    Im folgenden Codebeispiel wird eine Vorlagenklasse mit dem Namen MyTemplate dargestellt, die die ITemplate-Schnittstelle implementiert. In der MyTemplate-Klasse wird ein Konstruktor definiert, der den Wert einer ListItemType-Enumeration entgegennimmt, um den erstellten Vorlagentyp anzugeben. In Abhängigkeit vom Vorlagentyp werden mithilfe des Codes verschiedene Steuerelementtypen erstellt und einem PlaceHolder-Steuerelement hinzugefügt. Anschließend wird das Steuerelement zur Controls-Auflistung der übergeordneten Steuerelemente hinzugefügt. Für ListItemType von Item und von AlternatingItem wird ein Ereignishandler mit dem Namen Item_DataBinding erstellt.

    Die dargestellte Webseite enthält dadurch eine HTML-Tabelle mit einer anderen Hintergrundfarbe für jede zweite Elementvorlage.

    Public Class MyTemplate
        Implements System.Web.UI.ITemplate
    
        Dim templateType As ListItemType
    
        Sub New(ByVal type As ListItemType)
            templateType = type
        End Sub
    
        Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) _
          Implements System.Web.UI.ITemplate.InstantiateIn
    
            Dim ph As New PlaceHolder()
            Dim item1 As New Label()
            Dim item2 As New Label()
            item1.ID = "item1"
            item2.ID = "item2"
    
            Select Case (templateType)
                Case ListItemType.Header
                    ph.Controls.Add(New LiteralControl("<table border=""1"">" & _
                        "<tr><td><b>Category ID</b></td>" & _
                        "<td><b>Category Name</b></td></tr>"))
                Case ListItemType.Item
                    ph.Controls.Add(New LiteralControl("<tr><td>"))
                    ph.Controls.Add(item1)
                    ph.Controls.Add(New LiteralControl("</td><td>"))
                    ph.Controls.Add(item2)
                    ph.Controls.Add(New LiteralControl("</td></tr>"))
                    AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding)
                Case ListItemType.AlternatingItem
                    ph.Controls.Add(New LiteralControl("<tr bgcolor=""lightblue""><td>"))
                    ph.Controls.Add(item1)
                    ph.Controls.Add(New LiteralControl("</td><td>"))
                    ph.Controls.Add(item2)
                    ph.Controls.Add(New LiteralControl("</td></tr>"))
                    AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding)
                Case ListItemType.Footer
                    ph.Controls.Add(New LiteralControl("</table>"))
            End Select
            container.Controls.Add(ph)
        End Sub
    End Class
    
    public class MyTemplate : System.Web.UI.ITemplate
    {
        System.Web.UI.WebControls.ListItemType templateType;
        public MyTemplate(System.Web.UI.WebControls.ListItemType type)
        {
            templateType = type;
        }
    
        public void InstantiateIn(System.Web.UI.Control container)
        {
            PlaceHolder ph = new PlaceHolder();
            Label item1 = new Label();
            Label item2 = new Label();
            item1.ID = "item1";
            item2.ID = "item2";
    
            switch (templateType)
            {
                case ListItemType.Header:
                    ph.Controls.Add(new LiteralControl("<table border=\"1\">" +
                        "<tr><td><b>Category ID</b></td>" + 
                        "<td><b>Category Name</b></td></tr>"));
                    break;
                case ListItemType.Item:
                    ph.Controls.Add(new LiteralControl("<tr><td>"));
                    ph.Controls.Add(item1);
                    ph.Controls.Add(new LiteralControl("</td><td>"));
                    ph.Controls.Add(item2);
                    ph.Controls.Add(new LiteralControl("</td></tr>"));
                    ph.DataBinding += new EventHandler(Item_DataBinding);
                    break;                    
                case ListItemType.AlternatingItem:
                    ph.Controls.Add(new LiteralControl("<tr bgcolor=\"lightblue\"><td>"));
                    ph.Controls.Add(item1);
                    ph.Controls.Add(new LiteralControl("</td><td>"));
                    ph.Controls.Add(item2);
                    ph.Controls.Add(new LiteralControl("</td></tr>"));
                    ph.DataBinding += new EventHandler(Item_DataBinding);
                    break;
                case ListItemType.Footer:
                    ph.Controls.Add(new LiteralControl("</table>"));
                    break;
            }
            container.Controls.Add(ph);
        }
    }
    

So erstellen Sie einen Handler für das DataBinding-Ereignis

  1. Erstellen Sie entweder eine Methode, die Teil Ihrer Vorlagenklasse und Peer der anderen Klassenmethoden (wie z. B. InstantiateIn) ist, oder erstellen Sie eine statische (in Visual Basic Shared) Methode der Seite. Der Name des Handlers muss mit dem Namen übereinstimmen, den Sie zuvor bei der Ereignisbindung verwendet haben.

  2. Rufen Sie einen Verweis auf das DataItem-Objekt ab, das die Daten enthält, indem Sie folgende Schritte ausführen:

    1. Rufen Sie über die NamingContainer-Eigenschaft des Steuerelements einen Verweis auf das Vorlagenelement ab.

    2. Verwenden Sie diesen Verweis, um die DataItem-Eigenschaft des Benennungscontainers (d. h. des Vorlagenelements) abzurufen.

    3. Extrahieren Sie das einzelne Datenelement aus dem DataItem-Objekt, und verwenden Sie es, um eine Eigenschaft des zu bindenden Steuerelements festzulegen.

    Im folgenden Codebeispiel wird eine Möglichkeit veranschaulicht, die Datenbindung innerhalb einer dynamischen Vorlage durchzuführen. Im Beispiel wird ein vollständiger Ereignishandler zur Datenbindung für das PlaceHolder-Steuerelement sowie für das Literal-Steuerelement und das Label-Steuerelement dargestellt, die im zuvor beschriebenen Verfahren erstellt wurden. Der Ereignishandler wird als statische Methode der Seite implementiert.

    Shared Sub Item_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim ph As PlaceHolder = CType(sender, PlaceHolder)
        Dim ri As RepeaterItem = CType(ph.NamingContainer, RepeaterItem)
        Dim item1Value As Integer = _
            Convert.ToInt32(DataBinder.Eval(ri.DataItem, "CategoryID"))
        Dim item2Value As String = _
            Convert.ToString(DataBinder.Eval(ri.DataItem, "CategoryName"))
        CType(ph.FindControl("item1"), Label).Text = item1Value.ToString()
        CType(ph.FindControl("item2"), Label).Text = item2Value
    End Sub
    
    static void Item_DataBinding(object sender, System.EventArgs e)
    {
        PlaceHolder ph = (PlaceHolder)sender;
        RepeaterItem ri = (RepeaterItem)ph.NamingContainer;
        Int32 item1Value = (Int32)DataBinder.Eval(ri.DataItem, "CategoryID");
        String item2Value = (String)DataBinder.Eval(ri.DataItem, "CategoryName");
        ((Label)ph.FindControl("item1")).Text = item1Value.ToString();
        ((Label)ph.FindControl("item2")).Text = item2Value;
    }
    

Verwenden einer dynamischen Vorlage

Wenn Ihnen eine dynamische Vorlage zur Verfügung steht, können Sie diese programmgesteuert instanziieren.

So verwenden Sie eine dynamische Vorlage

  1. Erstellen Sie eine Instanz der dynamischen Vorlage, und übergeben Sie ihr einen entsprechenden Wert für den Elementtyp.

  2. Weisen Sie die Instanz einer der Vorlageneigenschaften des auf Vorlagen basierenden Steuerelements zu, wie z. B. den Eigenschaften ItemTemplate, AlternatingItemTemplate oder HeaderTemplate.

    Das folgende Codebeispiel zeigt, wie Sie die dynamische Vorlage mit einem Repeater-Steuerelement verwenden. In diesem Beispiel werden die Vorlagen instanziiert, während die Seite geladen wird und bevor das Steuerelement an seine Datenquelle gebunden wird.

    Im folgenden Beispiel wird davon ausgegangen, dass eine Verbindung mit der Northwind-Beispieldatenbank in Microsoft SQL Server 7.0 oder höher möglich ist. Es wird eine Liste von Datensätzen der Tabelle Kategorien zurückgegeben.

    Protected Sub Page_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    
        Dim conn As New System.Data.SqlClient.SqlConnection( _
            ConfigurationManager.ConnectionStrings("Northwind").ConnectionString)
    
        Dim sqlDataAdapter1 As System.Data.SqlClient.SqlDataAdapter
        Dim dsCategories1 As System.Data.DataSet
    
        sqlDataAdapter1 = New System.Data.SqlClient.SqlDataAdapter( _
            "SELECT [CategoryID], [CategoryName] FROM [Categories]", conn)
        dsCategories1 = New System.Data.DataSet()
    
        Repeater1.HeaderTemplate = New MyTemplate(ListItemType.Header)
        Repeater1.ItemTemplate = New MyTemplate(ListItemType.Item)
        Repeater1.AlternatingItemTemplate = New MyTemplate(ListItemType.AlternatingItem)
        Repeater1.FooterTemplate = New MyTemplate(ListItemType.Footer)
        sqlDataAdapter1.Fill(dsCategories1, "Categories")
        Repeater1.DataSource = dsCategories1.Tables("Categories")
        Repeater1.DataBind()
    
    End Sub
    
    protected void Page_Load(object sender, EventArgs e)
    {
        System.Data.SqlClient.SqlConnection conn =
            new System.Data.SqlClient.SqlConnection(
            ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);
    
        System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1;
        System.Data.DataSet dsCategories1;
    
        sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter(
            "SELECT [CategoryID], [CategoryName] FROM [Categories]", conn);
        dsCategories1 = new System.Data.DataSet();
    
        Repeater1.HeaderTemplate = new MyTemplate(ListItemType.Header);
        Repeater1.ItemTemplate = new MyTemplate(ListItemType.Item);
        Repeater1.AlternatingItemTemplate =
           new MyTemplate(ListItemType.AlternatingItem);
        Repeater1.FooterTemplate = new MyTemplate(ListItemType.Footer);
        sqlDataAdapter1.Fill(dsCategories1, "Categories");
        Repeater1.DataSource = dsCategories1.Tables["Categories"];
        Repeater1.DataBind();
    }
    

Ausführen des vollständigen Beispiels

Nachdem Sie alle zuvor aufgeführten Komponenten erstellt haben, fügen Sie dem Seitenmarkup ein Repeater-Steuerelement mit dem Namen Repeater1 hinzu, und führen Sie die Seite aus. Der vollständige Code und das Markup für die Webseite (unter Verwendung des Einzeldatei-Codemodells) sind im Folgenden dargestellt.

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script >

    Public Class MyTemplate
        Implements System.Web.UI.ITemplate

        Dim templateType As ListItemType

        Sub New(ByVal type As ListItemType)
            templateType = type
        End Sub

        Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) _
          Implements System.Web.UI.ITemplate.InstantiateIn

            Dim ph As New PlaceHolder()
            Dim item1 As New Label()
            Dim item2 As New Label()
            item1.ID = "item1"
            item2.ID = "item2"

            Select Case (templateType)
                Case ListItemType.Header
                    ph.Controls.Add(New LiteralControl("<table border=""1"">" & _
                        "<tr><td><b>Category ID</b></td>" & _
                        "<td><b>Category Name</b></td></tr>"))
                Case ListItemType.Item
                    ph.Controls.Add(New LiteralControl("<tr><td>"))
                    ph.Controls.Add(item1)
                    ph.Controls.Add(New LiteralControl("</td><td>"))
                    ph.Controls.Add(item2)
                    ph.Controls.Add(New LiteralControl("</td></tr>"))
                    AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding)
                Case ListItemType.AlternatingItem
                    ph.Controls.Add(New LiteralControl("<tr bgcolor=""lightblue""><td>"))
                    ph.Controls.Add(item1)
                    ph.Controls.Add(New LiteralControl("</td><td>"))
                    ph.Controls.Add(item2)
                    ph.Controls.Add(New LiteralControl("</td></tr>"))
                    AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding)
                Case ListItemType.Footer
                    ph.Controls.Add(New LiteralControl("</table>"))
            End Select
            container.Controls.Add(ph)
        End Sub
    End Class
    Shared Sub Item_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim ph As PlaceHolder = CType(sender, PlaceHolder)
        Dim ri As RepeaterItem = CType(ph.NamingContainer, RepeaterItem)
        Dim item1Value As Integer = _
            Convert.ToInt32(DataBinder.Eval(ri.DataItem, "CategoryID"))
        Dim item2Value As String = _
            Convert.ToString(DataBinder.Eval(ri.DataItem, "CategoryName"))
        CType(ph.FindControl("item1"), Label).Text = item1Value.ToString()
        CType(ph.FindControl("item2"), Label).Text = item2Value
    End Sub

    Protected Sub Page_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        Dim conn As New System.Data.SqlClient.SqlConnection( _
            ConfigurationManager.ConnectionStrings("Northwind").ConnectionString)

        Dim sqlDataAdapter1 As System.Data.SqlClient.SqlDataAdapter
        Dim dsCategories1 As System.Data.DataSet

        sqlDataAdapter1 = New System.Data.SqlClient.SqlDataAdapter( _
            "SELECT [CategoryID], [CategoryName] FROM [Categories]", conn)
        dsCategories1 = New System.Data.DataSet()

        Repeater1.HeaderTemplate = New MyTemplate(ListItemType.Header)
        Repeater1.ItemTemplate = New MyTemplate(ListItemType.Item)
        Repeater1.AlternatingItemTemplate = New MyTemplate(ListItemType.AlternatingItem)
        Repeater1.FooterTemplate = New MyTemplate(ListItemType.Footer)
        sqlDataAdapter1.Fill(dsCategories1, "Categories")
        Repeater1.DataSource = dsCategories1.Tables("Categories")
        Repeater1.DataBind()

    End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
    <title>Dynamically Creating Templates</title>
</head>
<body>
    <form id="form1" >
    <div>
      <asp:Repeater id="Repeater1" ></asp:Repeater>    
    </div>
    </form>
</body>
</html>
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script >

    public class MyTemplate : System.Web.UI.ITemplate
    {
        System.Web.UI.WebControls.ListItemType templateType;
        public MyTemplate(System.Web.UI.WebControls.ListItemType type)
        {
            templateType = type;
        }

        public void InstantiateIn(System.Web.UI.Control container)
        {
            PlaceHolder ph = new PlaceHolder();
            Label item1 = new Label();
            Label item2 = new Label();
            item1.ID = "item1";
            item2.ID = "item2";

            switch (templateType)
            {
                case ListItemType.Header:
                    ph.Controls.Add(new LiteralControl("<table border=\"1\">" +
                        "<tr><td><b>Category ID</b></td>" + 
                        "<td><b>Category Name</b></td></tr>"));
                    break;
                case ListItemType.Item:
                    ph.Controls.Add(new LiteralControl("<tr><td>"));
                    ph.Controls.Add(item1);
                    ph.Controls.Add(new LiteralControl("</td><td>"));
                    ph.Controls.Add(item2);
                    ph.Controls.Add(new LiteralControl("</td></tr>"));
                    ph.DataBinding += new EventHandler(Item_DataBinding);
                    break;                    
                case ListItemType.AlternatingItem:
                    ph.Controls.Add(new LiteralControl("<tr bgcolor=\"lightblue\"><td>"));
                    ph.Controls.Add(item1);
                    ph.Controls.Add(new LiteralControl("</td><td>"));
                    ph.Controls.Add(item2);
                    ph.Controls.Add(new LiteralControl("</td></tr>"));
                    ph.DataBinding += new EventHandler(Item_DataBinding);
                    break;
                case ListItemType.Footer:
                    ph.Controls.Add(new LiteralControl("</table>"));
                    break;
            }
            container.Controls.Add(ph);
        }
    }

    static void Item_DataBinding(object sender, System.EventArgs e)
    {
        PlaceHolder ph = (PlaceHolder)sender;
        RepeaterItem ri = (RepeaterItem)ph.NamingContainer;
        Int32 item1Value = (Int32)DataBinder.Eval(ri.DataItem, "CategoryID");
        String item2Value = (String)DataBinder.Eval(ri.DataItem, "CategoryName");
        ((Label)ph.FindControl("item1")).Text = item1Value.ToString();
        ((Label)ph.FindControl("item2")).Text = item2Value;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Data.SqlClient.SqlConnection conn =
            new System.Data.SqlClient.SqlConnection(
            ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);

        System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1;
        System.Data.DataSet dsCategories1;

        sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter(
            "SELECT [CategoryID], [CategoryName] FROM [Categories]", conn);
        dsCategories1 = new System.Data.DataSet();

        Repeater1.HeaderTemplate = new MyTemplate(ListItemType.Header);
        Repeater1.ItemTemplate = new MyTemplate(ListItemType.Item);
        Repeater1.AlternatingItemTemplate =
           new MyTemplate(ListItemType.AlternatingItem);
        Repeater1.FooterTemplate = new MyTemplate(ListItemType.Footer);
        sqlDataAdapter1.Fill(dsCategories1, "Categories");
        Repeater1.DataSource = dsCategories1.Tables["Categories"];
        Repeater1.DataBind();
    }


</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
    <title>Dynamically Creating Templates</title>
</head>
<body>
    <form id="form1" >
    <div>
      <asp:Repeater id="Repeater1" ></asp:Repeater>
    </div>
    </form>
</body>
</html>

Siehe auch

Weitere Ressourcen

Verwenden von ASP.NET-Webserver-Steuerelementen