ASP.NET控件开发学习笔记--第8回 WebControl分析
第8回 WebControl分析
在对WebControl进行分析之前,先把前面的控件做一个个修改。为了聚焦于我们要讨论的问题,将在控件中硬编码链接项目,不再使用xml文件。另外我们也知道,CSS可以直接写在标签的style属性内,这样也不再需要css文件,而直接硬编码到aspx文件内。
清空虚拟目录,新建一linkslist.aspx文件,在其中输入如下代码:
例8-1代码3:linkslist.aspx代码
<body>
<dl style="width:300px;margin:0;padding:2px;background: #ccc;">
<dt>我的导航控件</dt>
<dd>
<ul>
<li><a href='http://cgbluesky.blog.163.com/'target='_blank'>我的博客</a></li>
<li><a href='http://bbs.langsin.com/'target='_blank'>浪曦视频在线</a></li>
<li><a href='http://www.pup6.com/ebook.htm'target='_blank'>北京大学出版社第六事业部</a></li>
<li><a href='http://tech.163.com/school/video/'target='_blank'>网易学院</a></li>
<li><a href='http://tech.163.com/school/video/'target='_blank'>eNet硅谷动力网络学院</a></li>
</ul>
</dd>
</dl>
</body>
</html>
运行它,发现容颜已不再美丽,不要紧,现在还不是关心外表的时候。能运行就OK了。假设<body>内的HTML是由控件生成的,我们可以把它分为四个部分,如图8-1所示:
把它分成四个部分是基于一种假设:控件所生成的HTML代码全部包含在一对标签内,这叫主标签(这是我自己起的名字,未经ISO9000认证)。这一对主标签正是由图中的第一部分和第四部分的<dl></dl>标签对组成。而主标签可能存在一些属性或CSS样式,这就是第二部分。主标签内包含一些HTML代码或子标签,这就是第三部分。为什么要分为四部分呢?因为从Control继承的控件只需通过Render方法输出HTML,而从WebControl继承则需要把Render方法变为四个方法,这四个方法分别输出以上四个部分。为什么WebControl要这么做呢?多麻烦啊!因为如果你想要继承这个控件,并修改部分地方如主标签或CSS样式,这时只需要重写相应的方法就行了,不再需要完全覆盖整个Render方法,重新输出全部HTML。当然关于这一点看到后面大家会更容易理解些。
好,现在我们来看看WebControl的Render方法是如何实现的:
{
RenderBeginTag(writer);
RenderContents(writer);
RenderEndTag(writer);
}
可以看到WebControl的Render不再直接输出HTML,而是把这个工作代理给了三个方法。这时大家可能要问了,不是分为四个部分了吗?怎么只有三个啊?不要急,有一个部分在RenderBeginTag方法被调用了,这点在马上就讲到。我们来看每个方法的输出部分:
l RenderBeginTag:第一、二部分,主起始标签和它的属性。
l RenderContents:第三部分,主标签所包含的HTML。
l RenderEndTag:第四部分,主结束标签。
从这个Render方法可以想象得到,在WebControl中输出HTML需要override以上三个方法,这三个方法都是虚方法。
好,首先来看RenderBeginTag方法原型:
{
AddAttributesToRender(writer); //这个方法写主标签属性
if (TagKey != HtmlTextWriterTag.Unknown)
writer.RenderBeginTag(TagKey);
else
writer.RenderBeginTag(this.TagName);
}
可以看到AddAttributesToRender方法被放到了RenderBeginTag方法里,现在我们已经看到完整的四个部分。然后这里使用到了TagKey属性和TagName属性。它们是何许人也?TagKey是一个只读属性,它是一个HtmlTextWriterTag枚举类型,这个枚举类型包含了大部分我们常用的标签。但默认情况下TagKey指向<span>标签,那如果你的控件主标签是<table>该怎么办呢?这时就需要重写TagKey属性,如下:
{
get { return HtmlTextWriterTag.Table; }
}
真麻烦啊!以前在论坛上曾看到某人说.NET是一种包装过度的产品,现在有些同意。
这时有人可能还有疑问,如果使用的主标签不在HtmlTextWriterTag枚举里该怎么办啊?呵呵,这时就该TagName属性出场了,通过RenderBeginTag方法里的后四句代码您应该知道怎么用TagName属性了吧?就是先重写TagKey属性,把它设为HtmlTextWriterTag.Unknown,然后设置控件的TagName属性为你想要的标签就万事大吉了。呵呵,麻烦得到了进一步地增强。
下面讲讲RenderEndTag方法,它的原型为:
{
writer.RenderEndTag();
}
这里只是简单的调用RenderEndTag()方法,当然通过前面几回的学习,我们已经知道这个方法会根据相对应的起始标签生成匹配的结束标签。它的智能化很高,我们不需要太关心。好,现在我们来做个例子看看如何生成主标签。
在App_Code文件夹下新建一个linksList.cs文件,输入如下代码:
例8-2代码1:linksList.cs代码
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyControl
{
public class LinksControl:WebControl
{
protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.Table; }
}
}
}
呵呵,这个控件够简单,只重写了TagKey属性,也就是生成一对标签,什么都不显示。下面新建一linkslist.aspx文件,输入如下代码:
例8-2代码2:linkslist.aspx代码
<html>
<body>
<CG:LinksControl runat="server" />
</body>
</html>
这里只是简单地调用这个控件。运行它不会显示任何东西,在浏览器中选中【查看】菜单中的【源文件】打开网页的源码,现在看看是否生成了<table></table>标签对?
现在你对WebControl的运行机制有了一个大概的了解,但它远远没有这么简单,欲知后事如何,请听下回分解。