先说继承Control的情况,要输出控件内容,则重写Render方法,Control是根据里面的write输出什么就什么。里面的代码写法也有两种,一种是write输出一个长长的字符串,元素标识、属性值、子控件等等全都在里面,它直接,因此我最初就认为这就是我努力的方向;另一种是用write的AddAttribute、AddStyleAttribute、RenderBeginTag、RenderEndTag来输出,开头我还认为怎么有这么土的方式(冗长的代码是低手的象征),后来才感觉它的以下好处:写的代码整洁、有枚举可用,因此不容易写错(特别是样式名)、能自动适应各种浏览器、据说解析速度更快。这种方法要注意的是先输出属性或样式,再输出标志。还有一种方法:用WriteBeginTag与WriteEndTag,那是一种更原始的方法。
要了解得更深,还应该知道Render方法是什么时候调用的,可以通过Reflector来看其内容关系。Control的三个方法是:RenderControl、Render、RenderChildren,内部过程是:先执行RenderControl,里面的代码就是判断控件是否要显示,并且看是否启用跟踪,都没有只是执行Render方法。
public void RenderControl(HtmlTextWriter writer)
{
if (!this.flags[0x10])
{
HttpContext context = (this._page == null) ? null : this._page._context;
if ((context != null) && context.TraceIsEnabled)
{
int bufferedLength = context.Response.GetBufferedLength();
this.Render(writer);
int num2 = context.Response.GetBufferedLength();
context.Trace.AddControlSize(this.UniqueID, num2 - bufferedLength);
}
else
{
this.Render(writer);
}
}
}
而Render方法则更简单,只是调用RenderChildren方法
protected virtual void Render(HtmlTextWriter writer)
{
this.RenderChildren(writer);
}
RenderChildren方法则是看有没有被委托(还是叫截持?),如果没有再看自己有没有子控件,有就对子控件逐一执行RenderControl(又回到第一个方法,只是对象为子控件)
protected virtual void RenderChildren(HtmlTextWriter writer)
{
if (this._renderMethod != null)
{
this._renderMethod(writer, this);
}
else if (this._controls != null)
{
int count = this._controls.Count;
for (int i = 0; i < count; i++)
{
this._controls[i].RenderControl(writer);
}
}
}
知道了这个,就可以回答我们在重写Render时,不base.Render()都没问题,因为我们的控件下面没有子控件。
另外,RenderChildren中的事件委托可以用SetRenderMethodDelegate来设置,它的具体应用可以看“使用RenderMethod 委托实现DataGrid表头合并”http://space.zdnet.com.cn/html/05/250805-1001.html