ASP.NET服务器控件之RenderContents应用示例
相信读者在浏览各个网站时,经常会看到"联系我们"等类似文字。当单击这些文字时,操作系统将自动打开自身所带的邮件客户端软件,提示用户发送邮件。本例将实现一个自定义服务器控件RenderContentsControl,其用于通过呈现包含"mailto:邮件地址"的超链接。本例的示例效果图如图1所示:
如图1所示,页面中呈现了超链接文字"我的邮箱地址"。当单击该链接,系统将发送邮件给"my@mysample.com"。
在实现以上ASP.NET服务器控件之前,首先应分析如下:本控件包含外观元素,例如,文字大小、颜色、是否粗体等。为此,控件基类不应从Control类继承,而应从WebControl类继承。这样,开发人员将不必自行实现这些外观样式属性等内容。
下面列举了实现自定义服务器控件的RenderContentsControl.cs文件源代码。
using System;
using System.ComponentModel;
using System.Security;
using System.Security.Permissions;
using System.Web;using System.Web.UI;
using System.Web.UI.WebControls;
namespace UsingRenderContentsControl{
[
AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level = AspNetHostingPermissionLevel.Minimal),
DefaultProperty("Email"), ParseChildren(true, "Text"),
ToolboxData("﹤{0}:RenderContentsControl runat=server﹥﹤/{0}:RenderContentsControl﹥")
]
public class RenderContentsControl : WebControl {
// 实现Email属性
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")] [Localizable(true)]
public string Email
{
get {
String s = (String)ViewState["Email"];
return ((s == null) ? String.Empty : s);
}
set {
ViewState["Email"] = value;
}
}
// 实现Text属性
[
Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true),
PersistenceMode(PersistenceMode.InnerDefaultProperty)
]
public virtual string Text
{
get {
string s = (string)ViewState["Text"];
return (s == null) ? String.Empty : s;
}
set {
ViewState["Text"] = value;
}
}
// 重写TagKey属性
protected override HtmlTextWriterTag TagKey
{
get {
return HtmlTextWriterTag.A;
}
}
// 重写AddAttributesToRender方法
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Href, "mailto:" + Email);
}
// 重写RenderContents方法
protected override void RenderContents(HtmlTextWriter writer)
{
if (Text == String.Empty) {
Text = Email;
}
writer.WriteEncodedText(Text);
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
如上代码所示,RenderContentsControl类继承自WebControl基类,其原因在前文已经说明。另外,在RenderContentsControl类的实现过程中,还包括了元数据属性标记、3个属性(Email、Text和TagKey)和2两个方法(AddAttributesToRender和RenderContents)实现等内容。下面逐一对这些内容进行分析。
代码说明之3个属性:
在上文代码中主要包括了3个属性:Email、Text和TagKey。Email属性用于获取或者设置具体的电子邮件地址,Text属性用于获取或者设置控件显示的文本内容。在这两个属性实现中,都使用了控件视图状态ViewState。ASP.NET服务器控件的视图状态为其所有属性值的累计。对于简单属性的实现,将经常使用ViewState。TagKey属性是重写属性,其继承自WebControl基类,这是读者需要理解的重点内容。重写TagKey属性主要是为了呈现HTML标记中的a元素,这样就不会呈现WebControl类所默认呈现的span元素。此处,也暗示了本控件使用的构造函数是继承自WebControl的protected WebControl (),读者可返回上文再看看有关这个构造函数的说明。需要读者牢记的是:如果要呈现的元素是HtmlTextWriterTag枚举的成员,则应重写TagKey属性。许多常见的HTML元素标记被映射为HtmlTextWriterTag枚举的值。例如,System.Web.UI.HtmlTextWriterTag.A与a元素对应,而System.Web.UI.HtmlTextWriterTag.Table与table元素对应。如果要呈现的元素不是由HtmlTextWriterTag枚举的成员表示,那么建议重写TagName属性,并返回要作为元素呈现的字符串。
代码说明之2个方法:
在RenderContentsControl服务器控件中重写了2个重要方法:一个是AddAttributesToRender、另一个是RenderContents。
(1)AddAttributesToRender
该方法用于为ASP.NET服务器控件添加一个Href属性,并将该属性值设置为"mailto:Email",其中Email是上文所述的表示邮件地址的属性。当重写AddAttributesToRender方法时,应始终按照控件源代码演示的方式:首先,调用基类方法,然后进行相关设置。这样才能实现为服务器控件添加样式和其他属性的功能。实际上,根据前文所述的RenderBeginTag方法的实现示意性代码可知,AddAttributesToRender方法是由WebControl的RenderBeginTag方法调用。
(2)RenderContents
该方法是本示例的核心内容,其用于在ASP.NET服务器控件的标记中写入由Text属性指定的超链接文本。如代码所示,服务器控件调用了HtmlTextWriter实例的WriteEncodedText方法,以对开发人员输入的文本进行HTML编码。一般情况下,为了安全起见,应该对用户提供的文本进行HTML编码。
代码说明之元数据属性标记:
元数据属性标记在类前和属性实现前都有所应用。有关这些元数据属性标记的说明,在以前的文章中已经进行了具体说明。读者可查阅有关讲解如何创建一个简单的服务器控件的文章。下面重点说明一下有关内部文本持久性的问题。
在类前的元数据属性标记中,设置了ParseChildren(true, "Text")。在Text属性前的元数据属性标记中,设置了PersistenceMode(PersistenceMode.InnerDefaultProperty)。通过以上两个设置,则为控件添加了内部文本持久性设置。如此设置,可使得开发人员能够在控件标记代码内设置Text属性。例如:
﹤Sample:RenderContentsControl runat="server" ID="CustomerControl" Email="my@mysample.com"﹥我的邮箱地址﹤/Sample:RenderContentsControl﹥
在上面的代码中,原来文本"我的邮箱地址"应由Text属性设置(这就是默认持久性),然而,由于内部文本持久性设置,因此,可以在控件标记内设置控件文本。
实现内部持久性,应使用ParseChildren(true, "Text")来标记RenderContentsControl控件。ParseChildren的***个参数true,其用于指定页分析器应将控件标记内的内容分析为属性,而不是子控件。第二个参数提供控件的内部默认属性名称为Text。使用这两个参数调用ParseChildren构造函数时,控件标记内的内容必须与内部默认属性对应。Text属性的PersistenceMode(PersistenceMode.InnerDefaultProperty),用于指定可视化设计器应将此属性作为控件标记中的内部内容进行序列化。
通常,WebControl类使用PersistChildren(false)和ParseChildren(true)控制设计时和分析时属性的持久性。这两个属性将被控件继承,且仅在要更改继承的设置时需要应用。PersistChildren告知设计器是否应将ASP.NET服务器控件的子控件作为嵌套的内部控件保存。false参数指示内部内容与属性对应,而不是与子控件对应。ParseChildren已在上一段中加以说明。如果WebControl类的设计时和分析时持久性适用于您的控件,则不必重写从WebControl继承的PersistChildren和ParseChildren。
下面列举了用于测试服务器控件的Default.aspx文件源代码:
﹤%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %﹥
﹤%@ Register TagPrefix="Sample"
Assembly="UsingRenderContentsControl" Namespace="UsingRenderContentsControl" %﹥
﹤!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 id="Head1" runat="server"﹥
﹤title﹥使用RenderContents方法实现控件呈现﹤/title﹥
﹤/head﹥
﹤body﹥
﹤form id="form1" runat="server"﹥
﹤div﹥
﹤Sample:RenderContentsControl runat="server"
ID="CustomerControl" Font-Bold="true" Font-Size="small"
ForeColor="Blue" Email="my@mysample.com"﹥我的邮箱地址﹤/Sample:RenderContentsControl﹥
﹤/div﹥
﹤/form﹥
﹤/body﹥
﹤/html﹥
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
如上粗体代码所示,RenderContentsControl控件中设置了Font-Bold、Font-Size、ForeColor、Email等属性,同时,还在控件标记之间设置了文本内容。当然,如果开发人员将Text属性值设置为相同的文本内容也是可以的。以上代码比较简单,在此不再说明了。
通过这个示例,我们需要重点掌握RenderContents和AddAttributesToRender方法,以及TagKey属性的使用。提请读者注意的是虽然服务器控件的代码比较复杂,但是结构很简单。切不可被复杂的样式设置和客户端行为代码弄得不知所措,而是要注意体会两个重点方法的使用过程。
在服务器控件开发成功之后,***能够查看其HTML代码,并将服务器代码和HTML代码作以比较,搞清楚每一条ASP.NET服务器控件代码呈现了什么样的HTML代码。通过这个方法,相信读者能够对ASP.NET服务器控件的呈现方法有更加深刻的体会。下面列举了当用户在浏览器中运行以上页面,并查看相关的Html源文件时可得到的代码:
﹤!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 id="Head1"﹥
﹤title﹥ 使用RenderContents方法实现控件呈现﹤/title﹥
﹤/head﹥
﹤body﹥
﹤form name="form1" method="post" action="Default.aspx" id="form1"﹥
﹤div﹥
﹤input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwULLTEyNTQwNjQyMDJkZOlJ3PyMGs2hmzn9MU6Ogt9V+5ag" /﹥
﹤/div﹥
﹤div﹥
﹤a id="CustomerControl" href="mailto:my@mysample.com"
style="color:Blue;font-size:Small;font-weight:bold;"﹥我的邮箱地址﹤/a﹥
﹤/div﹥
﹤/form﹥
﹤/body﹥
﹤/html﹥
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
通过观察以上代码可知,自定义服务器控件RenderContentsControl实际呈现的结果是粗体所示部分的代码,其最终呈现为一个表示超链接的﹤a﹥标记,其中包括href、Style和文本等属性值。它们的值与Default.aspx文件源代码中,RenderContentsControl控件的属性设置有着密切关系。例如,Email属性值最终呈现为href属性值等等。读者可自行对照查看,这对于理解控件呈现很有益处。
小结
本文主要介绍了WebControl类的一些基本知识,并且利用这些基本知识创建了一个简单的控件呈现实例。实际上,从中读者应该能够总结出来,创建继承自WebControl基类的自定义服务器控件,其中最为重要的重写RenderContents方法。记住这一点是非常重要的。至此,笔者已经利用两篇文章来介绍实现控件呈现的方法。在以后的文章中,将介绍有关为ASP.NET服务器控件实现属性等方面的内容。
ASP.NET服务器控件之RenderContents应用示例的相关内容就向你介绍到这里,希望你能了解ASP.NET服务器控件之RenderContents的应用。【编辑推荐】
- ASP.NET服务器控件开发之实现事件浅析
- ASP.NET服务器控件之处理回传数据浅析
- ASP.NET服务器控件之捕获回传事件浅析
- ASP.NET控件开发基础之事件处理浅析
- ASP.NET服务器控件之RenderContents简介