所有的.ASPX页面都是System.Web.UI.Page类的实例。而Page类基层于TemplateControl类,TemplateControl类又继承于Control类,而且Page类和TemplateControl类都没有重载void RenderControl(HtmlTextWriter writer)方法。该方法是显示输出的第一个方法。由此可见,所有的.ASPX页面的输出都是从System.Web.UI.Page类的实例的void RenderControl(HtmlTextWriter writer)方法开始。
每个页面中都包含有各种各样的子控件,子控件又包含子控件,如何完整地输出?
其实,Control类的代码已经完全表达了递归输出的过程。使用Reflector.exe工具,从System.Web.DLL中,我们可以看到:
public virtual void RenderControl(HtmlTextWriter writer)
调用了
protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
调用了
private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
调用了
protected internal virtual void Render(HtmlTextWriter writer)
调用了
protected internal virtual void RenderChildren(HtmlTextWriter writer)
调用了
internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
调用了每个子控件的
public virtual void RenderControl(HtmlTextWriter writer)
如此,产生了一个循环,将所有的子控件都执行了输出方法。
从这里可以发现,如果我们创建了自定义的服务器控件,一旦重载Render方法,如果没有在方法的代码中执行基类的Render方法,就会中断自定义的服务器控件内部其他子控件的输出。这也是一些不明就里的程序员有可能会干的事。
从上述输出逻辑我们也可以发现,一个控件中在Render前包含的子控件,可能不会显示在页面内,关键看该控件的Render方法有没有执行RenderChildren方法。