.net控件开发(五)之 深入理解控件的呈现原理
首言 :
ASP.NET控件基本上都是继承Framework 已有三个基类,Control,WebControl,CompositeControl下面我就各个基类的呈现方法
讲述 Control,WebControl, CompositeControl 各自的呈现过程。
第一个: Control 呈现过程。
在 Control 所继承的控件的输出流程:
在正常的控件呈现输出 ( 就是说不是 ajax 控件里 , 在 ajax 会打乱此图 ) 中,它是一个循环调用的过程,看看下面的图就知道了 。
现在来分析分析其实现过程,在 Render 方法中调用另外一个名为 RenderChildren 的受保护成员,
该方法接收服务器控件内容的 HtmlTextWriter 对象 .
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
在此,我们什么时候给了 this._occasionalFields 赋值了呢。赋了什么值呢。当加入到控件树上时(使用了 findControl 查找控件),它会调用一个
private void EnsureNamedControlsTable
方法(这个方法在 findControl 中调用)去确保所有控件都被正确加载完成。
然后将其填充在一个控件集中
this .FillNamedControlsTable( this , this ._occasionalFields.Controls);,
从这里开始注意了, Ajax 异步回调与正常输出的控件是从这里开始分岐的。
1internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
2{
3/*
4this.RareFields如果设置这个参数,意谓着以自定义的方式去改写RenderChildern
5没有的话,将进行默态的流程对所有的子控件进行处理。
6![]()
7*/
8if (( this .RareFields != null ) && ( this .RareFields.RenderMethod != null ))
9{
10/* 调用RenderMethod委托,Asp.net Ajax在使用Control.SetRenderMethodDelegate时,对应的回调函数就是在此时处理的
11关于ajax的控件程现流程详见: http://www.cnblogs.com/liuxu-wxy/archive/2007/04/25/727346.html
12![]()
13*/
14writer.BeginRender();
15this .RareFields.RenderMethod(writer, this );
16writer.EndRender();
17}
18else if (children != null )
19{
20// 如果不设置这个RareFieldsEnsured,会把所有的控件呈现
21// 依次调用Control里所有子控件的RenderControl
22foreach (Control control in children)
23{
24control.RenderControl(writer); // 完成子控件的呈现过程
25}
26}
27}
28![]()
接下来就是真正呈现过程的入口方法
// 该方法为入口方法
public virtual void RenderControl(HtmlTextWriter writer)
{
this .RenderControl(writer, this .Adapter);
}
![]()
![]()
下面这段代码, 这个是一个过渡代码,其中的 this.flags[0x10] 没有搞明白是什么一回事,但不要紧。
它都会去调用 RenderControlInternal 方法
RenderControlInternal代码段
下面代码。控件是否有相关的呈现适配器,有的话就适配器调用适配器的相关呈现方法
private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
{
if (adapter != null )
{
// 调用相关的适配器方法
adapter.BeginRender(writer);
adapter.Render(writer);
adapter.EndRender(writer);
}
else
{
this .Render(writer);
}
}
![]()
理解就是 :
1. 控件开始呈现
2. 控件是否有相关的呈现适配器,有的话就适配器调用适配器的相关呈现方法
3. 呈现子控件
4. 完成控件呈现
第二个: WebControl 呈现过程
WebControl: 在 Control 的基础上增加了 Style ,呈现方面就是在 Render(HtmlTextWriter writer) 方法中扩展了三个呈现方法,增加一个属性呈现方法
流程图如下:
伪代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
第三个: CompositeControl 呈现过程
CompositeControl 类是一个抽象类,为自定义控件提供命名容器和控件设计器功能,该自定义控件包含全部子控件或使用其他控件功能。此类由 Login 和 Wizard 等控件继承
复合控件类必须派生自 System.Web.UI.WebControls.CompositeControl 类。这一点与 ASP.NET 1.x 环境下开发复合控件有些不同。在 ASP.NET 1.x 中,复合控件必须实现 System.Web.UI.INamingContainer 接口。然而,在 ASP.NET 2.0 下,复合控件类的基类则发生了变化
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
CompositeControl 重写了 WebControl 的 Render(HtmlTextWriter writer) ,增加了设计时支持以创建子控件
protected internal override void Render(HtmlTextWriter writer)
{
// 如果在设计时,创建子控件,也就是在设计时增加友好体验
if (DesignMode)
this .EnsureChildControls();
base .Render(writer);
}
————————————————————————————————————
后述: