Cómo: Crear plantillas de controles de servidor Web ASP.NET dinámicamente

Actualización: noviembre 2007

Cuando trabaja con controles con plantilla como por ejemplo el control DataList, es posible que no sepa hasta el tiempo de ejecución qué plantillas necesita o qué texto o controles debe contener la plantilla. En ese caso, puede crear dinámicamente plantillas en código.

Nota:

También se pueden crear plantillas como controles de usuario y enlazarlas de manera dinámica a los controles de la página pertinente. Para obtener información detallada, vea Cómo: Crear controles de usuario ASP.NET con plantillas.

Puede crear plantillas en el código para todos los controles que utilicen plantillas: DataList, Repeater, GridView, FormView y DetailsView. Para el control GridView, se utilizan plantillas para definir columnas en lugar de las plantillas de diseño de fila de los otros controles.

Nota:

Existen algunas diferencias a la hora de crear las columnas de plantilla para el control GridView. Para obtener información detallada, vea Crear una columna personalizada en un control de servidor Web GridView.

Crear una clase de plantilla

Para crear plantillas dinámicas, debe crear una clase de plantilla de la que pueda crear una instancia cuando sea preciso.

Para crear una clase de plantilla

  1. Cree una clase nueva que implemente la interfaz System.Web.UI.ITemplate.

  2. También puede pasar un valor al constructor de la clase que pueda utilizar la clase para determinar el tipo de plantilla que desea crear (ItemTemplate, AlternatingItemTemplate, etc.).

    Nota:

    Un modo seguro de pasar el tipo de plantilla al constructor consiste en agregar un parámetro al constructor con el tipo ListItemType. La enumeración ListItemType define los posibles tipos de plantilla para Repeater, DataList y otros controles.

  3. En la clase, implemente el método InstantiateIn, que es el miembro de la interfaz ITemplate.

    Este método proporciona un modo de insertar una instancia de texto y controles en el contenedor especificado.

  4. En el método InstantiateIn, cree los controles para el elemento de plantilla, defina las propiedades y agréguelas a la colección Controls del primario.

    Puede tener acceso al control primario a través de la referencia pasada al método InstantiateIn.

    Nota:

    No puede agregar texto estático directamente a la colección Controls, pero puede crear controles como Literal o LiteralControl, establecer sus propiedades Text y después, agregar dichos controles a la colección primaria.

    El siguiente ejemplo de código ilustra una clase de plantilla completa que muestra texto estático ("Item number:") y un contador. El contador se mantiene como un valor estático (compartido en Visual Basic) denominado itemcount e incrementa cada vez que se crea un nuevo elemento. La clase define un constructor explícito que acepta un valor de enumeración ListItemType para indicar el tipo de plantilla que se va a crear. Dependiendo del tipo de plantilla que se va a crear, el código crea tipos de control diferentes y los agrega a la colección Controls del control primario. El resultado final es una tabla HTML con un color de fondo diferente para la plantilla de elemento alterno.

    Public Class MyTemplate
        Implements ITemplate
        Shared itemcount As Integer = 0
        Dim TemplateType As ListItemType
    
        Sub New(ByVal type As ListItemType)
            TemplateType = type
        End Sub
    
        Sub InstantiateIn(ByVal container As Control) _
           Implements ITemplate.InstantiateIn
    
            Dim lc As New Literal()
    
            Select Case TemplateType
                Case ListItemType.Header
                    lc.Text = "<table border=""1""><tr><th>Items</th></tr>"
                Case ListItemType.Item
                    lc.Text = "<tr><td>Item number: " & itemcount.ToString _
                       & "</td></tr>"
                Case ListItemType.AlternatingItem
                    lc.Text = "<tr><td bgcolor=""lightblue"">Item number: " _
                       & itemcount.ToString & "</td></tr>"
                Case ListItemType.Footer
                    lc.Text = "</table>"
            End Select
    
            container.Controls.Add(lc)
            itemcount += 1
    
        End Sub
    End Class
    
    public class MyTemplate : ITemplate
    {
        static int itemcount = 0;
        ListItemType templateType;
    
        public MyTemplate(ListItemType type)
        {
            templateType = type;
        }
    
        public void InstantiateIn(System.Web.UI.Control container)
        {
            Literal lc = new Literal();
            switch (templateType)
            {
                case ListItemType.Header:
                    lc.Text = "<table border=\"1\"><tr><th>Items</th></tr>";
                    break;
                case ListItemType.Item:
                    lc.Text = "<tr><td>Item number: " + itemcount.ToString() +
                       "</td></tr>";
                    break;
                case ListItemType.AlternatingItem:
                    lc.Text = "<tr><td bgcolor=\"lightblue\">Item number: " +
                       itemcount.ToString() + "</td></tr>";
                    break;
                case ListItemType.Footer:
                    lc.Text = "</table>";
                    break;
            }
            container.Controls.Add(lc);
            itemcount += 1;
        }
    }
    
    

Utilizar la plantilla dinámica

Cuando tenga una plantilla dinámica disponible, puede crear una instancia de ella en el código.

Para utilizar una plantilla dinámica

  1. Cree una instancia de la plantilla dinámica y pásele un valor de tipo de elemento si procede.

  2. Asigne la instancia a una de las propiedades de plantilla del control con plantilla, como las propiedades ItemTemplate, AlternatingItemTemplate y HeaderTemplate.

    El siguiente ejemplo muestra cómo utilizar la plantilla dinámica con un control Repeater. En este ejemplo, se crean instancias de las plantillas mientras se carga la página y antes de enlazar el control a su origen de datos.

    Private Sub Page_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
    
        Dim conn As SqlConnection = _
          New SqlConnection(ConfigurationManager.ConnectionStrings("Northwind").ConnectionString)
        Dim SqlDataAdapter1 As SqlDataAdapter
        Dim DsCategories1 As DataSet
    
        SqlDataAdapter1 = New SqlDataAdapter("SELECT CategoryID, CategoryName FROM Categories", conn)
        DsCategories1 = new 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
    
    private void Page_Load(object sender, System.EventArgs e)
    {
        SqlConnection conn = 
          new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);
    
        SqlDataAdapter sqlDataAdapter1;
        DataSet dsCategories1;
    
        sqlDataAdapter1 = new SqlDataAdapter("SELECT CategoryID, CategoryName FROM Categories", conn);
        dsCategories1 = new 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();
    }
    

Enlazar datos a plantillas

Puede tener acceso a los datos en una clase de plantilla de distintas maneras, dependiendo de cómo ha creado la clase. Una manera es la forma en la que el marco de trabajo de la página implementa el enlace de datos; cuando agrega controles a la plantilla, también agrega un controlador para el evento DataBinding. Este evento se provoca una vez creado el elemento de plantilla con todos sus controles y le proporciona una oportunidad para obtener datos y utilizarlos en un control.

Nota:

No se puede incrustar una expresión de enlace de datos como una cadena cuando se crean controles en la plantilla, como se hace cuando se definen plantillas en tiempo de diseño, porque las expresiones de enlace de datos se convierten en código antes de que se cree la plantilla.

El controlador del evento DataBinding ofrece la oportunidad de manipular el contenido del control. Normalmente (pero no necesariamente), se toman datos de otro sitio y se asignan a la propiedad Text del control.

Nota:

Para obtener referencias sobre el enlace de datos en páginas Web ASP.NET, vea Obtener acceso a datos con ASP.NET.

Para agregar enlace a datos a una plantilla dinámica, debe realizar lo siguiente:

  • Agregue un controlador de eventos de enlace a datos a los controles que cree en la plantilla.

  • Cree el controlador con el que va a enlazar los datos. En el controlador, obtenga los datos que desee enlazar y asígnelos a la propiedad correspondiente del control que va a enlazar.

Para agregar el controlador de eventos de enlace a datos

  • Después de crear un control en la plantilla dinámica, agregue una referencia a un controlador de eventos para el evento DataBinding de control. (Creará el controlador de eventos en el procedimiento siguiente).

    El ejemplo de código siguiente muestra una parte de la clase de plantilla que indica cómo se puede enlazar un control recién creado a un método denominadoTemplateControl_DataBinding.

    Dim lc As New Literal()
    
    Select Case TemplateType
        Case ListItemType.Item
            lc.Text = "<tr><td>"
            AddHandler lc.DataBinding, AddressOf TemplateControl_DataBinding
    End Select
    
    case ListItemType.Item:
    
    lc.Text = "<tr><td>";
    lc.DataBinding += new EventHandler(TemplateControl_DataBinding);
    break;
    

    En el ejemplo anterior, el texto que agregue a la propiedad Text del control literal es diferente al del ejemplo anterior. Contiene sólo el principio de la fila y la celda de la tabla para la plantilla de elemento. Completará la celda y la fila en el controlador de eventos de enlace a datos.

El paso siguiente es crear el controlador de eventos al que se llamará cuando el control esté enlazado a datos.

Para crear el controlador para el evento DataBinding

  1. Cree un método que forme parte de la clase de plantilla al mismo nivel que los demás métodos de la clase (como InstantiateIn). El nombre del controlador debe coincidir con el nombre que utilizó antes para enlazar el evento. El método debe tener la siguiente firma:

    Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
    ByVal e As System.EventArgs)
    
    private void TemplateControl_DataBinding(object sender,
    System.EventArgs e)
    
  2. Obtenga una referencia al objeto DataItem que contiene los datos haciendo lo siguiente:

    1. Obtenga una referencia al elemento de plantilla. Cree una variable para albergar la referencia y asígnele el valor que obtenga de la propiedad NamingContainer del control.

    2. Utilice esa referencia para obtener la propiedad DataItem del contenedor de nomenclatura (elemento de plantilla).

    3. Extraiga el elemento de datos individual (columna de datos, por ejemplo) del objeto DataItem y utilícelo para definir una propiedad del control que va a enlazar.

      El siguiente código de ejemplo muestra un modo de enlazar a datos en una plantilla dinámica. Muestra un controlador de eventos de enlace a datos completo para controles Literal que se crean en una plantilla de un control Repeater.

      Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
      ByVal e As System.EventArgs)
      
          Dim lc As Literal
          lc = CType(sender, Literal)
      
          Dim container As RepeaterItem
      
          container = CType(lc.NamingContainer, RepeaterItem)
          lc.Text &= DataBinder.Eval(container.DataItem, "CategoryName")
          lc.Text &= "</td></tr>"
      End Sub
      
      private void TemplateControl_DataBinding(object sender,
      System.EventArgs e)
      {
      
          Literal lc;
      
          lc = (Literal)sender;
          RepeaterItem container = (RepeaterItem)lc.NamingContainer;
          lc.Text += DataBinder.Eval(container.DataItem, "CategoryName");
          lc.Text += "</td></tr>";
      }
      
      Nota:

      Si dispone de varios tipos de controles en sus plantillas, debería crear un controlador de eventos con enlace de datos para cada tipo de control.

Vea también

Otros recursos

Trabajar con controles de servidor Web ASP.NET