Go homepage(回首页)
Upload pictures (上传图片)
Write articles (发文字帖)

The author:(作者)delv
published in(发表于) 1/27/2014 6:45:55 AM
.net组件开发系列(五)之深入理解控件的呈现原理_[Asp.Net教程]

.net组件开发系列(五)之深入理解控件的呈现原理_[Asp.Net教程]

首言:
ASP.NET控件基本上都是继承Framework 已有三个基类,Control,WebControl,CompositeControl下面我就各个基类的呈现方法
讲述Control,WebControl, CompositeControl各自的呈现过程。


第一个:Control呈现过程。


在Control所继承的控件的输出流程:


在正常的控件呈现输出(就是说不是ajax控件里,在ajax会打乱此图)中,它是一个循环调用的过程,看看下面的图就知道了。


现在来分析分析其实现过程,在Render方法中调用另外一个名为RenderChildren的受保护成员,


该方法接收服务器控件内容的 HtmlTextWriter对象.



protected internal virtual void Render(HtmlTextWriter writer)
{
this.RenderChildren(writer);
}



protected internal virtual void RenderChildren(HtmlTextWriter writer)
{
/**//*
在这里this.occasionalFields中,它实现了OccasionalFields类,此类是一个sealed类,也就是一个不可继承的类,在其类中有一个Controls的public属性,返回的是一个控件集(ControlCollection)
在此处是用于维护其子控件列表的集合容器。


*/
ICollection children = (this._occasionalFields == null) ? null : ((ICollection) this._occasionalFields.Controls);


this.RenderChildrenInternal(writer, children);
}



在此,我们什么时候给了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*/
8 if ((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 */
14 writer.BeginRender();
15 this.RareFields.RenderMethod(writer, this);
16 writer.EndRender();
17 }
18 else if (children != null)
19{
20 //如果不设置这个RareFieldsEnsured,会把所有的控件呈现
21 //依次调用Control里所有子控件的RenderControl
22 foreach (Control control in children)
23 {
24 control.RenderControl(writer);//完成子控件的呈现过程
25 }
26 }
27}
28

接下来就是真正呈现过程的入口方法
//该方法为入口方法
public virtual void RenderControl(HtmlTextWriter writer)
{
this.RenderControl(writer, this.Adapter);
}



下面这段代码,这个是一个过渡代码,其中的this.flags[0x10]没有搞明白是什么一回事,但不要紧。
它都会去调用 RenderControlInternal方法
RenderControlInternal代码段
1protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
2{
3 if (!this.flags[0x10] && !this.flags[0x200])
4 {
5 HttpContext context = (this.Page == null) ? null : this.Page._context;
6 if ((context != null) && context.TraceIsEnabled)
7 {
8 int bufferedLength = context.Response.GetBufferedLength();
9 this.RenderControlInternal(writer, adapter);
10 int num2 = context.Response.GetBufferedLength();
11 context.Trace.AddControlSize(this.UniqueID, num2 - bufferedLength);
12 }
13 else
14 {
15 this.RenderControlInternal(writer, adapter);
16 }
17 }
18}
19
下面代码。控件是否有相关的呈现适配器,有的话就适配器调用适配器的相关呈现方法
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) 方法中扩展了三个呈现方法,增加一个属性呈现方法


流程图如下:



伪代码如下:



public virtual void RenderBeginTag(HtmlTextWriter writer)
{
this.AddAttributesToRender(writer);
//呈现Tag开始标记
}


protected override void Render(HtmlTextWriter writer)
{
//重写了Control的Render方法并增加了三个扩展方法
this.RenderBeginTag(writer);
this.RenderContents(writer);
this.RenderEndTag(writer);
}
protected internal virtual void RenderContents(HtmlTextWriter writer)
{
//调用Control的呈现
base.Render(writer);
}


public virtual void RenderEndTag(HtmlTextWriter writer)
{
//呈现结束标记
}


protected virtual void AddAttributesToRender(HtmlTextWriter writer)
{
//呈现Attribute
}



第三个: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下,复合控件类的基类则发生了变化


public abstract class CompositeControl : WebControl, INamingContainer, ICompositeControlDesignerAccessor
其余使用以后再讲,今天主要是讲其呈现过程;


CompositeControl 重写了WebControl的Render(HtmlTextWriter writer),增加了设计时支持以创建子控件


protected internal override void Render(HtmlTextWriter writer)
{
//如果在设计时,创建子控件,也就是在设计时增加友好体验
if (DesignMode)
this.EnsureChildControls();
base.Render(writer);
}


来源:suiqirui19872005的cnblogs







If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)




QQ:154298438
QQ:417480759