动态创建 Web 服务器控件模板

由于各种原因,直到运行时,您可能才会知道需要什么模板或模板中应包含哪些文本或控件。在这种情况下,您需要能够动态创建该模板(在代码中)。

注意   您还可以将模板创建为 Web 窗体用户控件,并将其动态绑定到页上的控件。有关详细信息,请参见创建模板用户控件

在代码中,您可以为所有使用模板的控件(DataListRepeaterDataGrid 控件)创建模板。对于 DataGrid 控件,您要使用的是定义列的模板,而不是其他两个控件的与行类似的模板。

注意   为 DataGrid 控件创建模板列时有一些差异。有关详细信息,请参见在 DataGrid 控件中以编程方式创建模板

创建模板类

要创建动态模板,请创建以后需要时可实例化的模板类。

注意   有关在 Visual Basic .NET 中创建类的背景,请参见了解类。有关 Visual C# .NET 的类似信息,请参见 class

创建模板类

  1. 创建新类,它可以实现 System.Web.UI 命名空间的 ITemplate 接口。
  2. 您也可以将值传递到类的构造函数。类可以使用该值来确定要创建的模板类型(ItemTemplateAlternatingItemTemplate 等)。
    提示   将模板类型传递到构造函数的类型安全方式是:给 ListItemType 类型的构造函数添加参数。ListItemType 枚举为 RepeaterDataList DataGrid 控件定义可能的模板类型。
  3. 在该类中,实现 InstantiateIn 方法(ITemplate 接口的唯一成员)。此方法提供将文本实例和控件实例插入指定容器的方法。
  4. InstantiateIn 方法中,为模板项创建控件,设置其属性,然后将它们添加到父级的 Controls 集合。您可以通过传递到 InstantiateIn 方法的引用访问父控件。
    注意   不能直接将静态文本添加到 Controls 集合,但可以创建类似 Literal 控件或 LiteralControl 控件的控件,设置它们的 Text 属性,然后将这些控件添加到父集合。

    下面的示例说明完整的模板类,该类显示某些静态文本(“Item number:”)和计数器。计数器是类的名为 itemcount 的共享值或静态值(根据您所用的语言),在每次创建新项时都会递增。

    该类定义一个接受 ListItemType 枚举值以指示所创建模板类型的显式构造函数。根据所创建的模板类型,代码创建不同类型的控件并将其添加到父控件的 Controls 集合。最终结果是一个 HTML 表,其中的交替项模板具有不同的背景色。

     

' Visual Basic
Private 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

// C#
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;
   }
}

  1. 使用动态模板

有了可用的动态模板,就可以在代码中将其实例化了。

注意   若要将动态模板作为 DataGrid 控件中的列使用,请参见在 DataGrid 控件中以编程方式创建模板

创建动态模板

  1. 创建动态模板的实例,如果合适的话,将一个项类型值传递给它。

将该实例分配给 Repeater 控件或 DataList 控件的模板属性之一:ItemTemplate、AlternatingItemTemplate、HeaderTemplate 等。

下面的示例显示如何与 Repeater 控件一起使用动态模板。在此示例中,在加载页时,而且是在控件绑定到数据源之前,将模板实例化。

 

' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
   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)
   Repeater1.DataBind()
End Sub

// C#
private void Page_Load(object sender, System.EventArgs e)
{
   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);
   Repeater1.DataBind();
}

  1. 向模板添加数据绑定

根据创建类的方法,从模板类访问数据的方式有多种。页结构自行实现数据绑定是一种好方法,因为您给模板添加控件时,也会为这些控件的 DataBinding 事件添加处理程序。在创建了模板项及其所有控件后,将会引发此事件,这样您就有机会获取并在控件中使用数据。

注意   在模板中创建控件时,您不能像在设计时定义模板那样,将数据绑定表达式作为字符串嵌入,因为数据绑定表达式会在页处理阶段(发生在创建您的模板之前)转换为代码。

DataBinding 事件的处理程序中,您有机会操作控件的内容。通常(并非一定),您从某处获取数据并将其分配给控件的 Text 属性。

注意   有关 Web 窗体页中数据绑定的背景信息,请参见 Web 窗体数据绑定

要将数据绑定添加到动态模板,必须执行如下操作:

  • 将数据绑定事件处理程序添加到您在模板中创建的控件。
  • 创建您要被绑定的处理程序。在该处理程序中,获取您要被绑定的数据并将其分配给要被绑定控件的相应属性。

添加数据绑定事件处理程序

  • 在动态模板中创建控件后,使用标准命令将控件的 DataBinding 事件绑定到稍后您将创建的方法。
    注意   有关如何动态添加事件处理程序的详细信息,请参见 AddHandler 和 RemoveHandler(对于 Visual Basic)和事件教程(对于 Visual C#)。

    下面的示例显示了模板类中的代码,该代码阐释了如何将新创建的控件绑定到名为 TemplateControl_DataBinding 的方法。

     

' Visual Basic
Dim lc As New Literal()
   Case ListItemType.Item
   lc.Text = "<TR><TD>"
   AddHandler lc.DataBinding, AddressOf TemplateControl_DataBinding

// C#
Literal lc = new Literal();
case ListItemType.Item:
   lc.Text = "<TR><TD>";
   lc.DataBinding += new EventHandler(TemplateControl_DataBinding);
   break;

  •  
  • 请注意,此示例中您添加到文本控件的 Text 属性的文本不同于上一示例。该示例只包含了项模板的表行和单元格的开头。您将在数据绑定事件处理程序中填写单元格和行。

下一步是创建事件处理程序,在控件处于数据绑定状态时将调用该事件处理程序。

为 DataBinding 事件创建处理程序

  1. 创建属于模板类的方法,作为该类的其他方法(如 InstantiateIn)的对等方法。处理程序的名称必须与早期绑定事件时使用的名称相匹配。该方法应该具有以下签名:

' Visual Basic
Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
   ByVal e As System.EventArgs)

// C#
private void TemplateControl_DataBinding(object sender,
   System.EventArgs e)

  1. 获取对包含当前模板项的数据的 DataItem 对象的引用。方法如下:
    1. 获取对模板项的引用。创建变量来保存该引用,然后将从您的控件的 NamingContainer 属性获取的值分配给它。
    2. 使用该引用来获取命名容器的(模板项的)DataItem 属性。
    3. DataItem 对象提取单个数据元素(例如,数据列)并使用它来设置您要绑定的控件的属性。

      下面的代码阐释在动态模板内执行数据绑定的一种方式。它显示了出在 Repeater 控件的模板中创建的 Literal 控件的完整数据绑定事件处理程序。

    ' Visual Basic
    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

    // C#
    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>";
    }

    1. 注意   如果在您的模板中具有多种类型的控件,您需要为每种控件类型创建不同的数据绑定事件处理程序。
posted @ 2010-09-21 15:39  庙子  阅读(465)  评论(0编辑  收藏  举报