“装装孙子”
上篇文章《开篇》说了不少空洞的理论,这篇文章我还是先说说“大而化之”的东西:1、ASP.net控件(包括页面本身)的生命期的细节;2、如何开始一个控件的编写。
“生死有序”
ASP.net处理程序在接收到一个用户的页面请求后,它是如何变戏法把一个鲜活的页面呈现给客户端的呢?它都做了哪些事?按什么顺序做的?
要说明这个问题,我们首先要明白,一个页面它本身也是一个Control。从设计模式的角度讲,页面模型是一个“合成模式(Composite)”,它本身是一棵由多层控件组成的结构树,顶层是Page,以下有叶有树枝,叶是不再包涵子控件的控件,枝是又包涵子控件的控件,每一层控件的生成都会调用一个生成子控件的方法,父控件调用子控件的生成方法,子又调用孙的,如此递归,保证页面中所有有效的(一般情况下是Visible=true)控件都得到生成过程处理,(有关设计模式的东西大家可以查看吕震宇老师在博客园的设计模式系列文章,该系列文章是对阎博士《Java与模式》一书(88元,很厚)的提炼与加工,至少可用来做设计模式浅层面速成的教材),而每个控件在生命周期大体都包括以下几个步骤:
1.实例化(Instantiate)
2.初始化(Initialize)
同上。
3.跟踪视图(Tracking View State)*
这个比较重要,涉及到视图状态,一般情况下不必重载此方法。
4.加载视图状态(Load view state)*
只会在回传过程中调用此方法,用法同上。
5.加载回传数据(Load postback data)*
如果你的控件生成之后要和客户端交互,那么这个方法就很重要,只会在回传过程中调用此方法。
6.开始载入(Load)
这个活动一般只是Page的OnLoad才会要去管它,我们写控件一般不要接触此方法。
7.有修改(Raise changed events)*
控件生成后,数据被客户端更改过,和加载回传数据是一路的。
8.回传事件处理(Raise postback event)*
一般用于实现IPostBackEventHandler接口的控件的把客户端事件转化成服务器端事件。只用于回传过程。
9.生成预处理(PerRender)**
生成前期工作,这个是很重要的一个过程,通过重载OnPreRender方法实现自定义。
10.保存视图状态(Save view state)*
如果所以信息都是用ViewState[xxx]这种方式来保存,不必重载,只有自定义视图状态管理时才重载此方法,当然,这里做了手脚,LoadViewState也就一定要和这里的Save方法配套。
11.生成(Render)***
这个是主角,控件成生什么东东基本就由这里管了。
12.卸载(Unload)
13.释放(Dispose)
了解控件的生命周期的细节对于我们自定义控件的各个部分以及调试控件,排除控件Bug都是至关重要的。
当然这此过程中有些活动是我们要特别重视的,我在这些活动的后面加了*号。
“装装孙子”
还记得我在上一篇文章中说.net框架已经为我们做了大部分的事情吗?确实,我们写一个控件不是平地起高楼,我们已经有了很多成品和半成品了。很多情况下,为了快速开发一个控件,你甚至可以使自己的控件直接继承于TextBox、Button之类具体的控件,略做修改,就可实现自己的功能。如果没有这样的好事,那你也最好考虑从以下两个类继承:System.Web.UI.Control、System.Web.UI.WebControls.WebControl,第一个类适合于派生生成不是可视HTML对象的控件,如生成<meta><xml>之类内容的控件,第二个类适合于生成各种HTML对象,它已经实现了基本的样式管理、HTML标签生成等等功能。
下一篇打算和大家探讨一下控件属性的方方面面,包括属性与HTML样式的aspx文件文本的关系,属性在VS中的高级编辑方法和在IDE中各种交互方式的定制等等
本文作者:未知