在本篇文章的第一部分,我们讨论了如何创建用户控件。在第二部分,我们将讨论如何创建定制控件。有三种方法可以创建定制控件:
.通过继承现有的控件创建派生定制控件。
.通过将现有的控件组合为新控件,创建复合控件。
.通过继承System.Web.UI.WebControls.WebControl创建完全定制的控件。
复合控件与用户控件极为相似,其主要差别是复合控件被编译为了DLL文件,我们能够象使用任何服务器控件那样使用定制控件。
在Visual Studio .NET中创建定制控件
打开Visual Studio .NET,选择“新工程”,在“新工程”窗口中选择“Visual C#工程”或“Visual Basic工程”,创建一个被称作CustomControls的Web控制库,如下图所示:

读者会注意到,Visual Studio已经创建了一个名字为WebCustomControl1的完整的定制控件。在研究该控件时,我们将先创建一个Web应用对该控件进行测试。从“文件”菜单中选择“新工程”,在同一个目录下创建一个名字为CustomControlWebPage的工程。注意,一定要选择“添加方案”单选按钮,如下图所示:

我们可以创建许多定制控件,并从该应用程序中对它们进行测试。右击CustomControls工程,调出快捷菜单,选择“属性”,如下图所示:

选择“配置属性”,将“输出路径”设置为与测试网页相同,如下图所示:

通常情况下,当我们建立定制控件时,就会将.DLL文件拷贝到对它进行测试的网页的\bin目录。通过将输出设置为测试网页的\bin目录,我们就能够省掉这一步。
缺省的定制控件
Visual Studio .NET已经提供了一个名字为WebCustomControl1的定制控件,这是一个由继承System.Web.UI.WebControls.WebControl得到的完整定制控件。在完全理解它之前,我们可以在创建的测试网页中对它进行测试。打开WebForm1.aspx,并在其中添加一条注册新控件的命令:
<%@Register TagPrefix="OReilly" Namespace="CustomControls" Assembly="CustomControls" %> |
上面的命令将向网页注册定制控件。我们再次使用了@Register标记,并提供了标记前缀(OReilly),而没有提供Tagname和src。但我们提供了能够唯一确定网页必须使用的控件、DLL的Namespace和Assembly。
现在我们可以在网页上添加控件了,其中有二个属性我们必须设置:所有的服务器端组件都必需的Runat和决定在运行时控件如何显示的Text,其标记应当如下所示:
| <OReilly:WebCustomControl1 Runat="Server" Text="Hello World!" Id="WC1" /> |
当浏览测试网页时,传递的网页将显示出来,如下图所示:

下面分别是Visual Studio .NET中提供的C#版和VB.NET版的完整定制控件:
VS.NET中缺省的定制控件(C#)
using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel;
namespace CustomControls { [DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 runat=server>")] public class WebCustomControl1 : System.Web.UI.WebControls.WebControl { private string text;
[Bindable(true), Category("Appearance"), DefaultValue("")] public string Text { get { return text; }
set { text = value; } }
protected override void Render(HtmlTextWriter output) { output.Write(Text); } } } |
VS.NET中缺省的定制控件(VB.NET)
Imports System.ComponentModel Imports System.Web.UI
WebCustomControl1>")> Public Class WebCustomControl1 Inherits System.Web.UI.WebControls.WebControl
Dim text As String
Property [Text]( ) As String Get Return text End Get
Set(ByVal Value As String) text = Value End Set End Property
Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) output.Write([Text]) End Sub
End Class |
该控制中只包含一个由private性质的字符串型变量text支持的特性Text。
表1:定制控件的通用属性
| 属性 |
描述 |
| Bindable |
布尔型,为true时表示VS.NET将在数据绑定对话框中显示该控件 |
| Browsable |
布尔型,表示该控件是否在设计视图中显示? |
| Category |
当Properties按类别排序时,决定控件所属的种类。 |
| DefaultValue |
缺省值。 |
| Description |
在Properties面板中的描述框中显示的文本内容。 |
特性
定制控件能够象其他类那样将特性提供给其他对象使用。我们能够通过编程或通过设置定制控件的属性值的方式访问这些特性:
控件的Text特性可以通过网页中的Text属性值进行访问。
在上面的Text特性和Text属性值这种情况中,属性值和特性之间的映射是非常简单的,因为它们都是字符串类型。当然了,ASP.NET会提供其他类型之间的智能转换。例如,如果特性的数据类型为整型或长整型,属性值就要被转换为适当的类型。如果值是枚举型数据,ASP.NET将对字符串值和枚举变量名字进行匹配,然后设置正确的枚举变量值。如果是布尔型数据,ASP.NET将对字符串型数据与布尔型数据的值进行匹配,也就是说,字符串“True”与布尔型数据值true是匹配的。
Render方法
定制控件的主要方法是Render,这一方法是在基本类中定义的,如果要控制对网页的绘制,我们就必须在派生类中覆盖它。在上面的例子中,Render方法使用HtmlTextWriter作为参数显示Text特性中的字符串。
HtmlTextWriter是由TextWriter派生生成的,提供了丰富的格式化功能。它能很好地组织生成的元素,并管理包括style在内的属性值。因此,如果想将文本设置为红色的,就可以添加一个红色属性值,如下所示:
| output.AddStyleAttribute("color", ColorTranslator.ToHtml(Color.Red)); |
我们还可以通过HtmlTextWriter的RenderBeginTag和RenderEndTag方法将文本设置在头部标记(<h2>)之间:
output.RenderBeginTag("h2"); output.Write(Text); output.RenderEndTag( ); |
上面代码运行的结果就是当文本输出时生成的正确的标记,如下图所示:

状态的维护
在下一个例子中,我们添加了一个使字体变大的按钮。为了实现这一功能,我们不能使用HtmlTextWriter的绘制功能,而应当通过使用新的Size特性(设置输出文本的大小)自己“写”这些文本。用C#编写的Render方法的代码如下:
protected override void Render(HtmlTextWriter output) { output.Write("" + Text + ""); } |
用VB.NET编写的Render方法代码如下:
Protected Overrides Sub Render(ByVal output As _ System.Web.UI.HtmlTextWriter) output.Write("" & [Text] & "") End Sub |
在点击该按钮后,Size特性必须维持其状态。这非常简单,它与读、写由网页维护的ViewState集合一样简单,Size特性在C#语言中的定义为:
public int Size { get { return Convert.ToInt32((string) ViewState["Size"]); } set { ViewState["Size"] = value.ToString( ); } }
|
Size特性在VB.NET中的定义如下:
Public Property Size( ) As Integer Get Return Convert.ToInt32(ViewState("Size")) End Get Set(ByVal Value As Integer) ViewState("Size") = Value.ToString( ) End Set End Property |
Get方法能够从ViewState中获取值,在C#中将获取的值指定为字符串型数据,然后将字符串转换为整型数据。Set方法将表示字体大小的字符串存入ViewState中。
为了保证在开始时ViewState中的值是有效的,我们还应当在该控件中添加一个构造器。构造器的C#代码如下:
public WebCustomControl1( ) { ViewState["Size"] = "1"; } |
构造器的VB.NET代码是:
Public Sub New( ) ViewState("Size") = "1" End Sub |
构造器将ViewState中的值初始化为1,每按一次该按钮,Size特性的值就会更新。为此,我们需要在网页中添加一个按钮定义:
Runat="server" Text="Increase Size" OnClick="Button1_Click" id="Button1" /> |
这里最重要的变化是添加了ID属性值(Button1),并为该按钮定义了一个事件处理程序。我们还需要在代码中定义一个事件处理程序。
一定要在网页上添加对CustomControls DLL文件的引用,这将使Intellisense知道我们的对象,而且能够在代码中定义控件。下面的C#代码将获得表单:
public class WebForm1 : System.Web.UI.Page { protected System.Web.UI.WebControls.Button Button1; protected CustomControls.WebCustomControl1 WC1; |
获得表单的VB.NET代码如下:
Public Class WebForm1 Inherits System.Web.UI.Page
Protected WithEvents Button1 As System.Web.UI.WebControls.Button Protected WC1 As VBCustomControls.WebCustomControl1 |
然后,我们就可以使用该定义设置在点击按钮的事件处理程序中的Size特性的值了,其C#代码如下:
public void Button1_Click(object sender, System.EventArgs e) { WC1.Size += 1; }
|
VB.NET代码与C#代码几乎完全相同:
Public Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click WC1.Size += 1 End Sub |
(出处:赛迪网) |