ASP.NET2.0服务器控件之创建自定义控件
实例所用源代码:http://file.ddvip.com/2007_05/1179934567_ddvip_5087.rar
摘要
本文将详细讲解一个简单的自定义服务器控件的创建过程。通过这些内容,读者将了解利用Visual Studio 2005,创建和测试自定义服务器控件的基本方法。
注意:本文内容基于ASP.NET 2.0技术撰写,示例应用程序使用Visual Studio 2005进行开发。
创建一个简单的自定义服务器控件
创建自定义服务器控件的过程包括:
(1)创建一个测试用Web站点应用程序;
(2)为新建站点应用程序,新增一个Web控件库项目;
(3)编写、编译和测试自定义服务器控件。
(1)创建一个测试用Web站点应用程序
利用Visual Studio 2005,创建Web站点应用程序的方法很多,例如,在本地文件系统中创建、在IIS支持下创建、在FTP站点中创建、在远程站点中创建等等。然而,无论如何,开发人员都应首先打开Visual Studio 2005,然后,单击"文件"菜单下"新建网站..."项目。这时,将弹出如下图1的对话框。
图1 新建网站对话框
图1是新建网站对话框。在该对话框中,开发人员需要选择创建模板,位置、编程语言。如图1所示,示例采用了ASP.NET网站模板,文件系统和C#编程语言来创建。当单击"确定"按钮之后,Visual Studio 2005将在本机D:AppTest下创建一个test1文件夹。所有应用程序文件都存储在文件夹内。默认情况下,test1文件夹内包括一个空的用于存储应用程序数据文件的App_Data文件夹,同时还分别包括一个Default.aspx和Default.aspx.cs文件。
通过以上步骤就创建了一个Web站点应用程序。该Web站点将用于测试所创建的Web自定义服务器控件。
(2)新增自定义服务器控件项目
在创建Web站点应用程序之后,开发人员还必须在当前站点项目中,添加一个自定义服务器控件项目,也就是Web控件库项目。实现方法是:在打开Web站点应用程序的前提下,单击"文件"菜单中"添加"项的子项"新建项目"。此时,Visual Studio 2005将弹出如图2的对话框。
图2 添加新项目对话框
图2是添加新项目对话框截图。该对话框分为三个设置部分:项目类型、模板、名称和位置。
在对话框左侧有一个树形列表,其中包括各种项目类型。为创建Web控件库项目,应选择"Visual C#"节点的子节点"Windows"。此时,对话框右侧将出现该子节点对应的已安装模板,其中包括Windows应用程序、类库、Web控件库等。开发人员应选中"Web控件库"一项。最后,需要设置Web控件库项目的名称和位置。为了便于管理,建议将Web控件库项目和测试站点项目存储在同一文件夹内,因此,本例将名称设置为"HelloMyControl",将位置设置为D:AppTest est1。当单击"确定"按钮之后,Visual Studio 2005将在D:AppTest est1目录下,自动创建一个HelloMyControl用于存储Web控件库相关文件。同时,Visual Studio 2005的"解决方案资源管理器"将显示如图3所示内容。
图3 解决方案资源管理器
如图3所示,解决方案资源管理器中包括两个项目。一个是前文创建的Web站点项目,另一个是名为HelloMyControl的Web控件库项目,其中默认包括一个WebCustomControl1.cs文件。下面就可以开始编写、编译和测试自定义服务器控件了。
(3)编写、编译和测试自定义服务器控件
需要实现的自定义服务器控件WelcomeLabel功能很简单。类似于一个标准Label控件。WelcomeLabel控件从System.Web.UI.WebControls. WebControl继承,其中自定义了一个string类型的Text属性。当控件运行时,将显示Text属性值和当前用户名的组合文字。例如,将Text属性值设置为"您好",那么最终显示的是"您好,某某!"。开发人员可以用WelcomeLabel控件作为站点欢迎页面的一部分。
WelcomeLabel控件的实现代码包含在WebCustomControl1.cs文件中。该文件源代码如下所示。
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace HelloMyControl
{
[
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
{
// 实现Text属性
[
Bindable(true), Category("Appearance"), DefaultValue(""), Description("文本内容."), Localizable(true)
]
public virtual string Text
{
get
{
string s = (string)ViewState["Text"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["Text"] = value;
}
}
// 重写RenderContents方法
protected override void RenderContents(HtmlTextWriter writer)
{
// 对Text属性值编码,并写入输入流中
writer.WriteEncodedText(Text);
// 判断Web请求是否有效。如果有效,则设置内容,并写入输出流中
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派生该控件。本例显然需要呈现用户界面元素,因此,自定义服务器控件类WelcomeLabel从WebControl基类继承。由于WebControl类从Control派生,因此,WelcomeLabel控件则自动继承基类提供的成员对象,这些对象多数与用户界面元素呈现有关,例如,Font、ForeColor、BackColor、Width等等。另外,同样也是由于从WebControl继承,因此,WelcomeLabel控件还自动实现ASP.NET 2.0新增的主题和皮肤功能。实际上,由于WelcomeLabel控件与ASP.NET 2.0的内置服务器控件Label有着很多相似之处,因此,从功能实现的角度出发,最好的方式应该是使得WelcomeLabel控件类从Label类继承。然而,本例为了说明定义属性和定义属性元数据的实现方法,因此,从WebControl基类继承。
代码说明之Text属性:
如上源代码所示,WelcomeLabel实现了一个Text属性,并使用视图状态存储该属性值。使用视图状态保存回发间的Text值。每次回发时,将重新创建页并从视图状态还原值。如果Text值并未存储在视图状态中,则在每次回发时会将值设置为其默认的Empty。ViewState属性继承自WebControl,是保存数据值的字典。通过使用String键,可输入和检索值。本例中将"Text"用作键。字典中的项被类型化为Object,然后必须将其强制转换为属性类型。
代码说明之RenderContents方法:
通常,在从WebControl派生控件并呈现单个元素时,应重写RenderContents方法(而不是Render方法),以呈现控件标记中的内容。在呈现控件及其样式属性的开始标记之后,WebControl的Render方法将调用RenderContents。如果重写Render方法以写入内容,则控件将丢失生成到WebControl的Render方法中的样式呈现逻辑。
在源代码中,WelcomeLabel控件重写了继承的RenderContents方法以呈现Text属性及其他一些内容。传入RenderContents方法的参数是HtmlTextWriter类型的对象,它是具有呈现标记和其他HTML(和HTML变量)标记的方法的实用工具类。可能读者已经注意到:WelcomeLabel连续调用了HtmlTextWriter对象的Write方法,而不是先执行字符串串联,然后调用Write方法。这种做法可提高控件性能。字符串串联需要时间和内存来创建字符串,然后写入流。
代码说明之元数据属性标记:
如上代码所示,在WelcomeLabel类声明前包括以下3个元数据属性标记。
(1)AspNetHostingPermissionAttribute
它是代码访问安全属性。该属性使JIT编译器检查链接到WelcomeLabel的代码是否具有AspNetHostingPermission权限。所有的公共ASP.NET类均使用此属性标记。应将AspNetHostingPermissionAttribute应用于控件,以对部分受信任的被调用方进行安全检查。
(2)DefaultPropertyAttribute
它是设计时属性(Attribute),它指定控件的默认属性(Property)。在可视化设计器中,当页开发人员在设计图面上单击控件时,属性浏览器通常突出显示此默认属性。
(3)ToolboxDataAttribute
它用于指定元素的格式字符串。如果在工具箱中双击控件或将其从工具箱拖动到设计图面上时,该字符串将成为控件的标记。对于WelcomeLabel,该字符串创建此元素:
<aspSample:WelcomeLabel runat="server"> </aspSample:WelcomeLabel>
另外,在属性Text的实现过程中还定义了以下元数据属性。
(1)BindableAttribute(被指定为true或false)
该元数据属性可用于指定将属性绑定到数据对可视化设计器是否有意义。例如,在VisualStudio2005中,如果属性标记为Bindable(true),则该属性可显示在"数据绑定"对话框中。如果属性(Property)没有使用此属性(Attribute)标记,则属性(Property)浏览器会推断其值为Bindable(false)。
(2)CategoryAttribute
该元数据属性用于指定如何在可视化设计器的属性浏览器中对属性进行分类。例如,当页开发人员使用属性浏览器的分类视图时,Category("Appearance")将告知属性浏览器在"外观"类别中显示属性。可以根据属性浏览器中的现有类别指定字符串参数,也可以创建自己的类别。
(3)DescriptionAttribute
该元数据属性用于指定属性的简短描述。在VisualStudio2005中,属性浏览器将在"属性"窗口底部显示选定的属性的描述。
(4)DefaultValueAttribute
该元数据属性用于指定属性的默认值。此值应与从属性访问器(getter)返回的默认值相同。在VisualStudio2005中,DefaultValueAttribute允许页开发人员通过在"属性"窗口中唤出快捷菜单然后单击"重置"按钮将属性值重置为其默认值。
(5)LocalizableAttribute(指定为true或false)
该元数据属性用于指定本地化属性对可视化设计器是否有意义。当某属性标记为Localizable(true)时,可视化设计器会在对本地化资源进行序列化时包含该属性。对控件轮询可本地化的属性时,设计器会将此属性值保存到非特定于区域性的资源文件或其他本地化源中。
在编写完成WelcomeLabel控件的源代码之后,接着需要编译和测试所实现的自定义服务器控件。为了实现这一目的,开发人员需要在测试用Web站点中引用Web控件库项目输出,并编写相关代码以便测试服务器控件。
在Web站点中实现Web控件库项目引用的方法比较简单。首先,右键单击解决方案资源管理器中的Web站点项目名称,在弹出的菜单中选中"添加引用..."一项。此时,将自动弹出如图4所示的窗口。
图4 添加引用对话框
如图4所示,在添加引用窗口中包括5个选项卡,其中包括一个名为"项目"的选项卡。单击它可发现在其列表中包括一个上文创建的HelloMyControl项目。选中该项并单击"确定"按钮,即可完成项目引用。
在完成项目引用后,Visual Studio 2005将自动在Web站点项目中添加一个Bin文件夹,并在其中包含了HelloMyControl.dll和HelloMyControl.pdb文件。前者是控件程序集,后者中则保存着调试和项目状态信息。这样,Web站点就能够顺利使用HelloMyControl项目的输出了。如下显示了为测试WelcomeLabel控件而创建的Default.aspx文件源代码。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register TagPrefix="self" Namespace="HelloMyControl" Assembly="HelloMyControl" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>创建一个简单的自定义服务器控件</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<self:WelcomeLabel Text="您好" ID="WelcomeLabel1" runat="server" BackColor="Wheat" ForeColor="SaddleBrown" />
</div>
</form>
</body>
</html>
如上粗体代码所示,页面首先利用@ Register指令将WelcomeLabel控件引入,然后,通过<self:WelcomeLabel>标记具体指示控件的位置,以及属性设置等。在<self:WelcomeLabel>标记中,主要设置了Text、BackColor和ForeColor属性,它们分别用于定义控件的文本内容、背景颜色和前景颜色。
如图5显示了执行Default.aspx的页面截图。
![](https://images.cnblogs.com/cnblogs_com/yssoft/1179934610_ddvip_5723.jpg)
图5 示例应用程序截图
小结
本文通过一个简单示例说明了实现自定义服务器控件的基本过程。通过这些内容,读者可能已经发现:创建自定义服务器控件与创建普通Web应用程序之间有着较大区别,这些差别主要体现在创建模式、所利用技术等方面。在随后的系列文章中,将详细探讨利用ASP.NET 2.0技术创建自定义服务器控件的相关内容。