《大步骤一》 初始化 装载视图 回传数据处理 ----初始化
《大步骤二》 加载事件 回传事件通知 触发回传事件 ----加载事件
《大步骤三》 预呈现 保存视图状态 呈现 ----呈现
《大步骤四》 卸载 释放资源 ----卸载并释放资源
下面具体说明控件生命周期的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/>");
}
}
}
【推荐】中国电信天翼云云端翼购节,2核2G云服务器一口价38元/年
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步