ASP.NET 揭秘 第二十九章 高级控件开发(ASP.MET)
1.Adding Templates to a Control
为控件添加模板
2.Creating DataBound Controls
建立数据绑定
3.Using Custom Controls and Web Services
自定义控件中使用Web服务
本章介绍部分建立自定义控件的高级主题,在第一部分,将介绍如何为控件添加模板,实现用户可自定义输出的控件模板;
接着,将练习数据绑定,将学习如何为控件添加充许用户绑定到名种数据源的属性,数据源可是是数据库中的表或其它集合.
最后,你将学习如何建立集成Web服务的控件,通过一个简单的控件返回并显示Web服务的信息.
1..Adding Templates to a Control(为控件添加模板)
许多标准的ASP.NET控件并支持模板功能(如Repeater, DataList, and DataGrid).通过为控件添加模板,你可以实现用户可自定义输出.
为了给控件添加模板,你需要完成以下几步的工作:
1>.为控件添加一个实现ITemplate 接口的属性来现实模板.
2>.建立一个新的控件包含模板的容器.(模板容器控件the template container control)
3>.通过调用模板集的InstantiateIn 方法,实例化模板容器控件中的模板.
以下示例中,自定义SimpleTemplate控件,该控件通过模板属性ItemTemplate 实现了ITemplate 接口.
同时,第二个控件TemplateItem是容器定义控件,这个控件是包含模板的容器.
最后,SimpleTemplate控件包含CreateChildControls子过程,通过该过程实例化TemplateItem控件.接着调用模板的InstantiateIn方法实例化TemplateItem控件中的各个模板元素.最终,将TemplateItem添加到SimpleTemplate控件的Controls集合中了.
Listing 29.1 SimpleTemplate.vb
Imports System
Imports System.Web
Imports System.Web.UI
Namespace myControls
Public Class TemplateItem
Inherits Control
Implements INamingContainer
Private _dataItem As String
Public Sub New( DataItem As String )
_dataItem = DataItem
End Sub
Public Property DataItem As String
Get
Return _dataItem
End Get
Set
_dataItem = Value
End Set
End Property
End Class
<ParseChildren(true)> Public Class SimpleTemplate
Inherits Control
Implements INamingContainer
Private _itemTemplate As ITemplate
Private _text As String
Public Property Text As String
Get
Return _text
End Get
Set
_text = Value
End Set
End Property
<TemplateContainer(GetType(TemplateItem))> _
Public Property ItemTemplate As ITemplate
Get
Return _itemTemplate
End Get
Set
_itemTemplate = Value
End Set
End Property
Public Overrides Sub DataBind()
EnsureChildControls()
MyBase.DataBind()
End Sub
Protected Overrides Sub CreateChildControls()
Dim objTemplateItem As TemplateItem
Controls.Clear()
objTemplateItem = New TemplateItem( Me.Text )
ItemTemplate.InstantiateIn( objTemplateItem )
Controls.Add( objTemplateItem )
End Sub
End Class
End Namespace
注:INamingContainer 接口标识在 Page 对象的控件层次结构内创建新 ID 命名空间的容器控件。这仅是一个标记接口。
ParseChildren用来指定控件的分析逻辑,它有bool一个参数,true表示控件标签中的内容解释为属性,解析器用一组内定的控件生器来解析嵌套的属性、子属性、模板、集合属性。你还可以用ParseChildren(true,"PropertyName")来指定嵌套内容传入哪个属性。
Control.EnsureChildControls 方法确定服务器控件是否包含子控件。如果不包含,则创建子控件。
CompiledTemplateBuilder.InstantiateIn 方法此方法支持 .NET 基础结构,但不适合在代码中直接使用。使用模板包含的子控件填充Control 对象。
以下代码使用上面的控件:
Listing 29.2 DisplaySimpleTemplate.aspx
<%@ Register TagPrefix="myControls" Namespace="myControls"
Assembly="SimpleTemplate"%>
<Script Runat="Server">
Sub Page_Load
DataBind()
End Sub
</Script>
<html>
<head><title>DisplaySimpleTemplate.aspx</title></head>
<body>
<form Runat="Server">
<myControls:SimpleTemplate
Text="Hello World!"
Runat="Server">
<ItemTemplate>
The value of DataItem is:
<b><%# Container.DataItem %></b>
</ItemTemplate>
</myControls:SimpleTemplate>
</form>
</body>
</html>
以上代码中的myTemplate 模板格式化输出SimpleTemplate 属性中的Text属性。通过模板Text属性中的值显示为粗体。
注意,在Page_Load中调用了DataBind()方法,DataBind方法引发ItemTemplate中所有的数据绑定.
Creating Multiple Instances of a Template(建立模板的多个实例)
当你建立模板之后,你可以在控件实例化多次模板。例如:如果你希望建立一个显示数据1到10的控件,假设你需要为用个数据添加一个模板。以下代码可以实现:
Listing 29.3 TemplateNumbers.vb
Imports System
Imports System.Web
Imports System.Web.UI
Namespace myControls
Public Class TemplateNumbersItem
Inherits Control
Implements INamingContainer
Private _dataItem As Integer
Public Sub New( DataItem As Integer )
_dataItem = DataItem
End Sub
Public Property DataItem As Integer
Get
Return _dataItem
End Get
Set
_dataItem = Value
End Set
End Property
End Class
<ParseChildren(true)> Public Class TemplateNumbers
Inherits Control
Implements INamingContainer
Private _numberTemplate As ITemplate
<TemplateContainer(GetType(TemplateNumbersItem))> _
Public Property NumberTemplate As ITemplate
Get
Return _numberTemplate
End Get
Set
_numberTemplate = Value
End Set
End Property
Public Overrides Sub DataBind()
EnsureChildControls()
MyBase.DataBind()
End Sub
Protected Overrides Sub CreateChildControls()
Dim intCounter As Integer
Dim objTemplateNumbersItem As TemplateNumbersItem
Controls.Clear()
For intCounter = 1 To 10
objTemplateNumbersItem = New TemplateNumbersItem( intCounter )
NumberTemplate.InstantiateIn( objTemplateNumbersItem )
Controls.Add( objTemplateNumbersItem )
Next
End Sub
End Class
End Namespace
以下代码使用上面的控件:
Listing 29.4 DisplayTemplateNumbers.aspx
<%@ Register TagPrefix="myControls" Namespace="myControls"
Assembly="TemplateNumbers"%>
<Script runat="Server">
Sub Page_Load
DataBind()
End Sub
</Script>
<html>
<head><title>DisplayTemplateNumbers.aspx</title></head>
<body>
<form Runat="Server">
<myControls:TemplateNumbers
Runat="Server">
<NumberTemplate>
<li><i><%# Container.DataItem %></i>
</NumberTemplate>
</myControls:TemplateNumbers>
</form>
</body>
</html>
Adding Multiple Templates to a Control
为控件添加多个模板
在某些情况下,你可能需要为控件添加多个模板,例如标准的ASP.NET控件Repeater 就包含6个模板:HeaderTemplate, ItemTemplate, AlternatingItemTemplate, SeparatorTemplate, and FooterTemplate.
这时原理同上,只需要为控件添加多个实现ITemplate接口的属性就可以了。
以下示例中MultipleTemplate控件有两个模板属性: ItemTemplate and AlternatingItemTemplate.
Listing 29.5 MultipleTemplates.vb
Imports System
Imports System.Web
Imports System.Web.UI
Namespace myControls
Public Class MultipleTemplatesTemplateItem
Inherits Control
Implements INamingContainer
Private _dataItem As Integer
Public Sub New( DataItem As Integer )
_dataItem = DataItem
End Sub
Public Property DataItem As Integer
Get
Return _dataItem
End Get
Set
_dataItem = Value
End Set
End Property
End Class
<ParseChildren(true)> Public Class MultipleTemplates
Inherits Control
Implements INamingContainer
Private _itemTemplate As ITemplate
Private _alternatingItemTemplate As ITemplate
<TemplateContainer(GetType(MultipleTemplatesTemplateItem))> _
Public Property ItemTemplate As ITemplate
Get
Return _itemTemplate
End Get
Set
_itemTemplate = Value
End Set
End Property
<TemplateContainer(GetType(MultipleTemplatesTemplateItem))> _
Public Property AlternatingItemTemplate As ITemplate
Get
Return _alternatingItemTemplate
End Get
Set
_alternatingItemTemplate = Value
End Set
End Property
Public Overrides Sub DataBind()
EnsureChildControls()
MyBase.DataBind()
End Sub
Protected Overrides Sub CreateChildControls()
Dim intCounter As Integer
Dim objTemplateItem As MultipleTemplatesTemplateItem
Controls.Clear()
For intCounter = 1 To 10
objTemplateItem = New MultipleTemplatesTemplateItem( intCounter )
If Decimal.Remainder( intCounter, 2 ) = 0 Then
ItemTemplate.InstantiateIn( objTemplateItem )
Else
AlternatingItemTemplate.InstantiateIn( objTemplateItem )
End If
Controls.Add( objTemplateItem )
Next
End Sub
End Class
End Namespace
以下代码使用上面的控件:
Listing 29.6 DisplayMultipleTemplates.aspx
<%@ Register TagPrefix="myControls" Namespace="myControls"
Assembly="MultipleTemplates"%>
<Script runat="Server">
Sub Page_Load
DataBind()
End Sub
</Script>
<html>
<head><title>DisplayMultipleTemplates.aspx</title></head>
<body>
<form Runat="Server">
<myControls:MultipleTemplates
Runat="Server">
<ItemTemplate>
<li><i><%# Container.DataItem %></i>
</ItemTemplate>
<AlternatingItemTemplate>
<li><h2><%# Container.DataItem %></h2>
</AlternatingItemTemplate>
</myControls:MultipleTemplates>
</form>
</body>
</html>
在MultipleTemplates 的定义中,ItemTemplate模板格式化输出的文字为斜体字,AlternatingItemTemplate格式化输出的文字为HTML中的标记<H2>