要创建的控件 WelcomeLabel 是一个简单控件,与标准的 Label 控件类似。WelcomeLabel 类从 WebControl 派生,它定义了一个 Text 属性,该属性允许页开发人员提供一个文本字符串,以欢迎访问站点的用户。如果用户名出现在用户浏览器发送的标题中,WelcomeLabel 就会将用户名追加到该文本字符串。有关检索用户名的更多信息,请参见 User。例如,如果页开发人员将“Hello”设置为 Text 属性的值,则根据标题中是否出现用户名,WelcomeLabel 将呈现“Hello, 用户名!”或“Hello!”。
创建自定义服务器控件的代码
-
创建一个名为 WelcomeLabel.cs 或 WelcomeLabel.vb 的文件。
-
将以下代码添加到控件的源文件中:
' WelcomeLabel.vb
Option Strict On
Imports System
Imports System.ComponentModel
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace Samples.AspNet.VB.Controls
< _
AspNetHostingPermission(SecurityAction.Demand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
DefaultProperty("Text"), _
ToolboxData( _
"<{0}:WelcomeLabel runat=""server""> </{0}:WelcomeLabel>") _
> _
Public Class WelcomeLabel
Inherits WebControl
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The welcome message text."), _
Localizable(True) _
> _
Public Overridable Property Text() As String
Get
Dim s As String = CStr(ViewState("Text"))
If s Is Nothing Then s = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("Text") = value
End Set
End Property
Protected Overrides Sub RenderContents( _
ByVal writer As HtmlTextWriter)
writer.WriteEncodedText(Text)
If Context IsNot Nothing Then
Dim s As String = Context.User.Identity.Name
If (s IsNot Nothing) AndAlso (s <> String.Empty) Then
Dim split() As String = s.Split("\".ToCharArray)
Dim n As Integer = split.Length - 1
If (split(n) <> String.Empty) Then
writer.Write(", ")
writer.Write(split(n))
End If
End If
End If
writer.Write("!")
End Sub
End Class
End Namespace
// WelcomeLabel.cs
using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Samples.AspNet.CS.Controls
{
[
AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level=AspNetHostingPermissionLevel.Minimal),
DefaultProperty("Text"),
ToolboxData("<{0}:WelcomeLabel runat=\"server\"> </{0}:WelcomeLabel>")
]
public class WelcomeLabel : WebControl
{
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The welcome message text."),
Localizable(true)
]
public virtual string Text
{
get
{
string s = (string)ViewState["Text"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["Text"] = value;
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
writer.WriteEncodedText(Text);
if (Context != null)
{
string s = Context.User.Identity.Name;
if (s != null && s != String.Empty)
{
string[] split = s.Split('\\');
int n = split.Length - 1;
if (split[n] != String.Empty)
{
writer.Write(", ");
writer.Write(split[n]);
}
}
}
writer.Write("!");
}
}
}
代码讨论
下面的代码讨论并不是执行此演练中的步骤必不可少的内容,可以在开始时跳过。但是,如果您初学控件创作,我们建议您至少要在完成演练后阅读此内容。
如果控件要呈现用户界面 (UI) 元素或任何其他客户端可见的元素,则应从 System.Web.UI.WebControls.WebControl(或派生类)派生该控件。如果控件要呈现在客户端浏览器中不可见的元素(如隐藏元素或 meta 元素),则应从 System.Web.UI.Control 派生该控件。WebControl 类从 Control 派生,并添加了与样式相关的属性,如 Font、ForeColor 和 BackColor。此外,一个从 WebControl 派生的控件也自行参与到 ASP.NET 的主题功能。
如果您的控件要扩展现有控件(如 Button、Label 或 Image 控件)的功能,则可以从该控件派生。由于 WelcomeLabel 扩展了 Label 控件的功能,因此它可从 Label 派生。但是,本演练从 WebControl 派生 WelcomeLabel 以演示如何定义属性和定义属性元数据。
WelcomeLabel 定义一个 Text 属性,并使用视图状态存储该属性值。使用视图状态保存回发间的 Text 值。每次回发时,将重新创建页并从视图状态还原值。如果 Text 值并未存储在视图状态中,则在每次回发时会将值设置为其默认的 Empty。ViewState 属性继承自 WebControl,是保存数据值的字典。通过使用 String 键,可输入和检索值。本例中将“Text”用作键。字典中的项被类型化为 Object,然后必须将其强制转换为属性类型。有关更多信息,请参见 ASP.NET 状态管理概述。
WelcomeLabel 控件通过重写继承的 RenderContents 方法呈现其 Text 属性。传入 RenderContents 方法的参数是 HtmlTextWriter 类型的对象,是具有呈现标记和其他 HTML(和 HTML 变量)标记的方法的实用工具类。
注意,WelcomeLabel 会连续调用 HtmlTextWriter 对象的 Write 方法,而不是先执行字符串串联然后调用 Write 方法。由于 HtmlTextWriter 对象直接写入输出流,因此这样可以提高性能。字符串串联需要时间和内存来创建字符串,然后写入流。在控件中实现呈现时,应按照本演练中说明的模式进行操作。
注意 |
|---|
| 通常,在从 WebControl 派生控件并呈现单个元素时,应重写 RenderContents 方法(而不是 Render 方法),以呈现控件标记中的内容。在呈现控件及其样式属性的开始标记之后,WebControl 的 Render 方法将调用 RenderContents。如果重写 Render 方法以写入内容,则控件将丢失生成到 WebControl 的 Render 方法中的样式呈现逻辑。有关呈现从 WebControl 派生的控件的更多信息,请参见 Web 控件呈现示例。 |
应用于 WelcomeLabel 的属性包含由公共语言运行库和设计时工具使用的元数据。
在类级别上,通过以下属性标记 WelcomeLabel :
WelcomeLabel 控件还从 WebControl 基类继承了两个属性:ParseChildrenAttribute 和 PersistChildrenAttribute。它们被应用为 ParseChildren(true) 和 PersistChildren(false)。这两个属性 (Attribute) 一起与 ToolboxDataAttribute 属性 (Attribute) 共同使用,这样可将子元素解释为属性 (Property),并将属性 (Property) 作为属性 (Attribute) 保留。
以下应用于 WelcomeLabel 的 Text 属性 (Property) 的属性 (Attribute) 是标准设计时属性 (Attribute),通常会将标准设计时属性 (Attribute) 应用于控件的所有公共属性 (Property):
-
BindableAttribute(被指定为 true 或 false),指定将属性绑定到数据对可视化设计器是否有意义。例如,在 Visual Studio 2005 中,如果属性标记为 Bindable(true),则该属性可显示在“数据绑定”对话框中。如果属性 (Property) 没有使用此属性 (Attribute) 标记,则属性 (Property) 浏览器会推断其值为 Bindable(false)。
-
CategoryAttribute 指定如何在可视化设计器的属性浏览器中对属性进行分类。例如,当页开发人员使用属性浏览器的分类视图时,Category("Appearance") 将告知属性浏览器在“外观”类别中显示属性。可以根据属性浏览器中的现有类别指定字符串参数,也可以创建自己的类别。
-
DescriptionAttribute 指定属性的简短描述。在 Visual Studio 2005 中,属性浏览器将在“属性”窗口底部显示选定的属性的描述。
-
DefaultValueAttribute 指定属性的默认值。此值应与从属性访问器 (getter) 返回的默认值相同。在 Visual Studio 2005 中,DefaultValueAttribute 允许页开发人员通过在“属性”窗口中唤出快捷菜单然后单击“重置”按钮将属性值重置为其默认值。
-
LocalizableAttribute(指定为 true 或 false)指定本地化属性对可视化设计器是否有意义。当某属性标记为 Localizable(true) 时,可视化设计器会在对本地化资源进行序列化时包含该属性。对控件轮询可本地化的属性时,设计器会将此属性值保存到非特定于区域性的资源文件或其他本地化源中。
注意 |
|---|
| 由于 ASP.NET 1.0 版和 1.1 版中的 ASP.NET 本地化模型不同,因此在这些版本中不能将 LocalizableAttribute 应用于自定义服务器控件。 |
应用于控件及其成员的设计时属性在运行时不会影响控件的功能,但在可视化设计器中使用控件时,这些属性能提升开发人员的体验。有关服务器控件的设计时、分析时和运行时属性的完整列表,可参见自定义服务器控件的元数据属性。