大家在平时学习Asp.Net进行web开发时,为了满足项目需要,将开发大量满足需求的自定义控件。那关于自定义控件的生命周期如何呢,与页面生命周期有何区别呢?我今天跟大家详细解释一下:控件生命周期大概有11个阶段,对于特殊的页面(其实也是一种控件System.Web.UI.Page)的生命周期有更详细的阶段,比如对于每一种控件来说,都只有一个Init事件,但是Page对同一个事件却分成了PreInit, Init, InitComplete三个阶段。其具体的职责如下:
PreInit: 完成模板页和主题的设置,只有这一次机会,一旦到了Init阶段将不能更改。
Init: 依次触发子控件的Init事件,进而执行对应的OnInit方法,完成子控件的初始化和设置命名容器。
InitComplete: 使控件具体视图跟踪能力。
下面具体说明控件生命周期的11阶段:
1.初始化(对应OnInit方法)
完成控件的初始化并通过ProcessRequest方法递归遍历所有的子控件以及依次调用它们的OnInit方法。可以通过重写OnInit方法来扩展功能或增加初始化内容。除此之外,本阶段将打开控件的视图跟踪功能(调用TraceViewState方法),这样才能在页面回发时正确恢复控件的属性。
2.加载视图状态(对应LoadViewState方法)
本阶段仅在页面回发时才执行,事实上,在第一次访问页面时还没有获取到存储在视图状态中的数据。本阶段完成加载视图状态到控件(前提是该控件启用视图状态),对于复杂对象则需要重写LoadViewState方法和SaveViewState方法。在每一次客户端请求过程中,视图状态存储在隐藏控件中,每次请求都会将ViewState回传到服务器,以便在服务器回传数据以及判断是否执行相应的回发事件。
3.加载回传数据(对应LoadPostData方法)
本阶段仅在页面回发时才执行,LoadPostData是实现接口IPostBackDataHandler的一个方法(主要实现控件数据回传)。该方法有一个参数NameValueCollection类型对象,装载了客户端提交的数据。根据控件旧值和新值比较是否一致,决定是否执行下面的RaisePostDataChangedEvent方法。具体过程如下:客户端修改窗体的数据提交后,接受的数据以“&”符号隔开的一些键值对,页面处理器根据传递的数据控件集合,根据匹配ID对应的服务器控件是否实现IPostBackDataHandler接口,如实现此接口则调用控件的LoadPostData方法以刷新其值,否则不调用。
4.装载(对应OnLoad方法)
注意,页面装载时先执行页面的Page_Load事件再依次递归执行各个子控件的OnLoad方法。本阶段控件树结构中的所有控件已经创建并完成初始化,且状态已还原和回传给客户端,可以重写OnLoad方法完成一些所有请求共有的操作,还可以通过IsPostBack判断控件是在第一次请求页面还是回发页面时执行自定义初始化代码逻辑。
5.数据回传事件通知(对应RaisePostDataChangedEvent方法)
本阶段仅在页面回发时才执行,RaisePostDataChangedEvent是实现接口IPostBackDataHandler的一个方法(主要实现控件数据回传事件)。与LoadPostData匹配使用,当前者返回true时,才调用RaisePostDataChangedEvent方法。
6.触发回发事件(对应RaisePostBackEvent方法)
本阶段仅在页面回发时才执行,主要处理引起回发的客户端事件,成功捕获回发的客户端事件进行服务端的相应处理。前提是实现IPostBackEventHandler接口。可以判断是哪个控件引发的回发事件,从而进行不同的事件处理。
7.预呈现(对应OnPreRender方法)
本阶段主要完成控件呈现(Render)之前的一些工作,一般自定义控件都会重写方法,对资源进行注册(Javascript和隐藏域)。
8.保存视图状态(对应SaveViewState方法)
与LoadViewState过程正好相反,SaveViewState用于存储页面视图状态信息。SaveViewState在第一次页面请求时就会执行,而LoadViewState仅在页面回发时执行。
9.呈现(对应Render方法)
本阶段主要完成控件标记和字符文本输出到服务器控件的输出流中。可以直接写Html,也可调用控件的RenderControl输出到流中。
10.卸载(对应OnUnload方法)
本阶段将清除页面的资源。OnUnload仅是一个控件生命周期内的事件,如果认为该方法会在离开页面时或点击关闭按钮时触发是不正确的,因为页面两次请求是无状态的,而因为Asp.Net视图状态机制看起来好像连续的。
11.释放(对应Dispose方法)
本阶段将释放资源(数据库连接,IO文件等)。
了解了吗?如果理解了,我将这个过程用代码的形式描述出来,希望能有一个更加直观的认识。
[DefaultProperty("Text")]
[ToolboxData("<{0}:ControlLifeCycle runat=server></{0}:ControlLifeCycle>")]
public class ControlLifeCycle : WebControl, IPostBackDataHandler, IPostBackEventHandler
{
/// <summary>
/// 1. 初始化
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
Output("1. OnInit");
base.OnInit(e);
this.Page.RegisterRequiresPostBack(this);
}
/// <summary>
/// 2. 装载视图
/// </summary>
/// <param name="savedState"></param>
protected override void LoadControlState(object savedState)
{
Output("2. LoadControlState");
base.LoadControlState(savedState);
}
/// <summary>
/// 3. 回传数据处理
/// </summary>
/// <param name="postDataKey"></param>
/// <param name="postCollection"></param>
/// <returns></returns>
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
Output("3. LoadPostData");
return true;
}
/// <summary>
/// 4. 加载事件
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
Output("4. OnLoad");
base.OnLoad(e);
}
/// <summary>
/// 5. 回传事件通知
/// </summary>
public virtual void RaisePostDataChangedEvent()
{
Output("5. RaisePostDataChangedEvent");
}
/// <summary>
/// 6. 触发回传事件
/// </summary>
/// <param name="eventArgument"></param>
public virtual void RaisePostBackEvent(string eventArgument)
{
Output("6. RaisePostBackEvent");
}
/// <summary>
/// 7. 预呈现
/// </summary>
/// <param name="e"></param>
protected override void OnPreRender(EventArgs e)
{
Output("7. OnPreRender");
base.OnPreRender(e);
}
/// <summary>
/// 8. 保存视图状态
/// </summary>
/// <returns></returns>
protected override object SaveViewState()
{
Output("8. SaveViewState");
base.SaveViewState();
return new Pair();
}
/// <summary>
/// 9. 呈现
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<input type='button' name='{0}' value='Click Me' style='position:absolute;left:20px;top:280px' onclick=\"{1}\"/>",
"[控件生命周期]", Page.ClientScript.GetPostBackEventReference(this, ""));
Output("9. Render");
base.Render(writer);
}
/// <summary>
/// 10. 卸载
/// </summary>
/// <param name="e"></param>
protected override void OnUnload(EventArgs e)
{
Output("10. OnUnload");
base.OnUnload(e);
}
/// <summary>
/// 11. 释放资源
/// </summary>
public override void Dispose()
{
Output("11. Dispose");
base.Dispose();
}
private void Output(string content)
{
if (!this.DesignMode)
{
HttpContext.Current.Response.Write(content + "<br/>");
}
}
}
以上就是自定义控件的整个生命周期,明白了这些,开发自定义控件时将游刃有余。