ASP.NET服务器控件编程架构(二)
Asp.net服务器控件的呈现阶段发生在控件的Render生命周期内(倒数第二个生命周期,参考ASP.NET服务器控件生存周期),这个时候控件所有的初始化工作,加载工作,回转数据处理及状态视图的保存都已完成。接下来的任务就是将其转换成能在客户端代理(如web浏览器)上呈现的代码(如html)。
我们先来介绍Control类的呈现架构。Control类的呈现架构有三个方法:
1. Render方法(受保护),此方法接收一个HtmlTextWriter类型的参数,将输出流转化为html流。Control类的Render方法默认实现代码为调用RenderChildren方法(如下),所以当重写此方法时,如果控件包含子控件一定要调用父类的方法(base.Render())此方法的原型为:
... {
RenderChildren();
}
2. RenderCotrol方法(公有)此方法实际上是调用Render方法,当控件的Visible属性为真时就调用Render方法,为假时便不调用,所以当控件的Visible属性为假时根本没有将其转化为html代码。RenderControl方法为页面后者其父控件调用,在可视设计工具中,呈现引擎也要调用。方法原型为:
... {
if(this.Visible)
...{
this.Render(writer);
}
}
3. RenderChildred方法(受保护),此方法循环遍历控件的子控件集合(Controls)属性,依次调用子控件的RenderControl方法,原型如下: Control类的呈现架构就是这样在三个方法之间递归的调用,以便把控件的逻辑呈现为html代码。
... {
foreach(Control child in this.Contorls)
...{
child.RenderControl(writer);
}
}
下面看一下WebControl的呈现架构。
WebControl继承自Control,除了继承了Control的属性和方法外,它还实现了与样式有关的很多属性,如BackgoundColor,Font,Border等。当我们要实现一个有用户界面的控件时最好继承WebControl,因为与样式有关的属性我们可以直接使用。而不必去写很多不必要的代码(在本文的最后我会举一个分别继承自WebControl和Control类的实现相同功能的例子)。
WebControl的呈现架构有许多方法和属性,下面我列举一些比较重要的详细介绍一下。
1. Render方法(受保护),WebControl重写了Control类的Render方法,在其内部依次调用RenderBeginTag方法,RenderContent方法,RenderEndTag方法。这三个方法都是WebControl类新加的。RenderBeginTag方法输出THML的开始标签,RenderContent方法输出HTML的内容,RenderEndTag方法输出HTML的结束标签。而RenderBeginTag方法又调用了AddAttributeToRender方法,此方法把与控件相关的属性添加到标签内,如ID属性,样式属性等,所以当我们重写AddAttributeToRender方法是一定要调用基类的方法,否则我们会丢失一些很重要的信息。
2. TagKey属性(受保护),此属性是HtmlTextWriterTag类型的属性,提供WebControl类的开始标签,其默认的为span。
这样介绍你可能会觉得很乱,下面我列出这些重要方法的原型,以便于理解。
Render方法:
RenderBeginTag方法:
... {
AddAttributeToRander(writer);
if (this.TagKey != HtmlTextWriterTag.Unknown)
...{
writer.WriteBeginTag(this.TagKey);
}
else
...{
writer.WriteBeginTag(this.TagName);
}
}
RenderContent方法和RenderEndTag方法
... {
//content;
}
protectRenderEndTag(HtmlTextWriter writer)
... {
writer.WriteEndTag();
}
... {
base.Render(writer);
RenderBeginTag(writer);
RenderContent(writer);
RenderEndTag(writer);
}
TagKey属性;
... {
Return HtmlTextWriterTag.Span;
}
下面给出一个实例,这个简单的例子实现了一个叫simapleDiv的控件,为方便在继承Contorl的时候我只给它实现了一个FontColor属性(其实你可以实现更多)。我们可以更改它的FontColor属性以便在客户端呈现不同的颜色。
继承自Control类的:
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;
namespace XiuYanger.ProCSharp.Concrols
... {
[DefaultProperty("Text")]
public class SimpleDiv1 : Control
...{
//Text property
[
Category("Appearance"),
DefaultValue(""),
Description("The text in the div lable."),
]
public string Text
...{
get
...{
object o = ViewState["Text"];
return (o == null) ? string.Empty : (string)o;
}
set
...{
ViewState["Text"] = value;
}
}
//FontColor Property
[
Category("Appearance"),
DefaultValue(typeof(Color), "Black"),
Description("The text in the div lable."),
TypeConverter(typeof(WebColorConverter))
]
public Color FontColor
...{
get
...{
object o = ViewState["FontColor"];
return (o == null) ? Color.Black : (Color)o;
}
set
...{
ViewState["FontColor"] = value;
}
}
//override RenderMothed
protected override void Render(HtmlTextWriter writer)
...{
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
writer.AddStyleAttribute(HtmlTextWriterStyle.Color, ColorTranslator.ToHtml(FontColor));
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.Write(this.Text);
writer.RenderEndTag();
}
}
}
继承自WebControl类的:
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;
namespace XiuYanger.ProCSharp.Concrols
... {
[DefaultProperty("Text")]
public class SimpleDiv:WebControl
...{
//Text property
[
Category("Appearance"),
DefaultValue(""),
Description("The text in the div lable."),
]
public string Text
...{
get
...{
object o=ViewState["Text"];
return (o == null) ? string.Empty : (string)o;
}
set
...{
ViewState["Text"]=value;
}
}
//override KeyTag property
protected override HtmlTextWriterTag KeyTag
...{
get
...{
return HtmlTextWriterTag.Div;
}
}
//override RenderContentMethod
protected override void RenderContents(HtmlTextWriter writer)
...{
writer.Write(this.Text);
}
}
}
由于WebControl类实现了Color属性所以在此没有实现,至于例子中有些代码,下篇解释。
由于篇幅,原定于在这一节中讲解HtmlTextWriter类,只好放到下一节中。敬请关注!