在以前寫個(gè)一篇關(guān)于ASP.NET頁(yè)面生命周期的草稿,最近又看了看ASP.NET,做個(gè)補(bǔ)充,看看頁(yè)面初始過(guò)程到底是怎么樣的
下面是ASP.NET頁(yè)面初始的過(guò)程:
1. Page_Init();
2. Load ViewState;
3. Load Postback data;
4. Page_Load();
5. Handle control events;
6. Page_PreRender();
7. Page_Render();
8. Unload event;
9. Dispose method called;
下面對(duì)其中的一些過(guò)程作下描述:
1. Page_Init();
這個(gè)過(guò)程主要是初始化控件,每次頁(yè)面載入執(zhí)行這個(gè)初始過(guò)程,包括第一次和以后的Postback(這里說(shuō)下Postback,其實(shí)就可以簡(jiǎn)單理解成用戶點(diǎn)擊SUBMIT按鈕之類的,把表單<Form>提交給服務(wù)器,這就是一次postback),在這里面可以訪問(wèn)控件,但是這里面的控件值不是我們期待的控件里面的值,他只是一個(gè)控件的初始值(默認(rèn)值),舉例: 比如一個(gè)TextBox1,我們填入了"哈哈",在點(diǎn)擊SUBMIT提交了頁(yè)面后,在Page_Init()里面,我們?cè)L問(wèn)到的TextBox1.Text不是我們的"哈哈",而是開(kāi)始的""空字符串,如果TextBox1在我們?cè)O(shè)計(jì)的時(shí)候提供了默認(rèn)值,這里訪問(wèn)到的也就是提供的默認(rèn)值,為什么呢,這就要看下一個(gè)過(guò)程了.
對(duì)應(yīng)的事件Page.Init
2. Load ViewState
這個(gè)過(guò)程是載入VIEWSTATE和Postback數(shù)據(jù),比如我們上面的TextBox1,這時(shí)就賦了"哈哈",所以,在Post_Init()對(duì)控件賦值是無(wú)意義的,它都會(huì)在這個(gè)過(guò)程里被改寫,當(dāng)然第一次頁(yè)面載入例外,因?yàn)闆](méi)有VIEWSTATE數(shù)據(jù)。
沒(méi)有對(duì)應(yīng)的事件
3.Load Postback data;
上面說(shuō)了,Postback可以理解成用戶提交表單數(shù)據(jù),所以這里就是處理表單數(shù)據(jù),當(dāng)然這里要設(shè)計(jì)到控件的設(shè)計(jì),一般情況不會(huì)要我們自己處理這個(gè)過(guò)程,我們暫且略過(guò). (在以前那篇關(guān)于ASP.NET頁(yè)面生命周期的簡(jiǎn)單描述中,把這個(gè)過(guò)程和Load ViewState放在了一起,其實(shí)那是微軟提供的生命周期過(guò)程,這里單獨(dú)提出來(lái)是為了讓大家明白這是一個(gè)單獨(dú)的過(guò)程)
沒(méi)有對(duì)應(yīng)的事件
4. Page_Load();
這個(gè)過(guò)程也是每次頁(yè)面載入時(shí)一定會(huì)執(zhí)行的,但是注意和Page_Init的區(qū)別,上面已經(jīng)涉及了,這里注意的是一般都會(huì)用到Page.IsPostBack,該值指示該頁(yè)是否正為響應(yīng)客戶端回發(fā)而加載,或者它是否正被首次加載和訪問(wèn)。
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
//第一次執(zhí)行的CODE HERE
}
else
{
//用戶提交FORM(即Postback)CODE HERE
}
//每次這里的都回執(zhí)行CODE HERE
}
對(duì)應(yīng)的事件Page.Load
5. Handle control events;
這個(gè)過(guò)程里,相應(yīng)具體的控件事件,比如private void ListBox1_SelectedIndexChanged(object sender, System.EventArgs e)事件等等
沒(méi)有對(duì)應(yīng)的事件(我們自己的事件函數(shù)都包括在這個(gè)過(guò)程里比如上面的ListBox1_SelectedIndexChanged)
6. Page_
預(yù)先呈遞對(duì)象,這里是在向用戶程序呈現(xiàn)數(shù)據(jù)的倒數(shù)第二步,我估計(jì)提供這個(gè)過(guò)程的意義,也就是在這里能對(duì)控件屬性等等要呈現(xiàn)給用戶的數(shù)據(jù)進(jìn)行修改,這也是最后的修改,以前的修改(比如在Page_Init里面)都可能被覆蓋.做完這了還會(huì)進(jìn)行一個(gè)操作就是保存狀態(tài),即SaveViewState.
對(duì)應(yīng)的事件時(shí)Page.PreRender
7. Page_Render();
大家可以在瀏纜器里View->Source查看到,每個(gè)頁(yè)面都有一個(gè)隱藏的<input>,這里面的"__VIEWSTATE"就是我們服務(wù)器寫回來(lái)的頁(yè)面狀態(tài)信息,在 這個(gè)之前,服務(wù)器要呈現(xiàn)頁(yè)面(也就是構(gòu)造HTML格式的文件),就是從這個(gè)"__VIEWSTATE"里面獲取的數(shù)據(jù),當(dāng)然大家也注意到了,這里有個(gè) Page.Render事件,我們可以添加自己的處理代碼,也就是說(shuō)我們又可以更改數(shù)據(jù),不過(guò)這里推薦不要在這里修改,既然提供了PreRender,就 應(yīng)該在里面做最后的修改,當(dāng)然這不是必須的,只是推薦!
對(duì)應(yīng)的事件Page.Render
8. Unload event;
大家應(yīng)該明白,當(dāng)想服務(wù)器請(qǐng)求一個(gè)對(duì)象的時(shí)候,就會(huì)在內(nèi)存里生成一個(gè)繼承頁(yè)面對(duì)象,也就是頁(yè)面的類,它繼承自System.Web.UI.Page.
當(dāng)頁(yè)面對(duì)象從內(nèi)存中卸載時(shí)發(fā)生,將觸發(fā)該事件.
對(duì)應(yīng)的事件Page.Unload
9. Dispose method called;
銷毀所有的對(duì)象.當(dāng)從內(nèi)存釋放Page時(shí)發(fā)生,這是生存期的最后階段??赡艿?和9似乎有些模糊,不過(guò)我也沒(méi)怎么搞清楚,待研究!
對(duì)應(yīng)的事件Dispose
以上就是ASP.NET頁(yè)面周期的描述。
注意上面灰色背景的文字,如果一個(gè)過(guò)程中有對(duì)應(yīng)的事件,我們可以自己定義一個(gè)函數(shù)(當(dāng)然先在MSDN中找到函數(shù)原型),然后在
InitializeComponent中向事件的鏈表上添加上去,像下面:
private void InitializeComponent()
{
this.Unload += new System.EventHandler(this.MainWebForm_Unload);
this.Load += new System.EventHandler(this.Page_Load);
this.Init += new System.EventHandler(this.Page_Init);
this.PreRender += new System.EventHandler(this.My_PreRender);
}
對(duì)于幾個(gè)沒(méi)有對(duì)應(yīng)事件的過(guò)程,比如2.Load ViewState,我們可以重載Page的虛函數(shù)protected override void LoadViewState(object savedState);來(lái)添加自己的控制代碼,不過(guò)切忌掉用基類的對(duì)應(yīng)方法,比如:
protected override void LoadViewState(object savedState)
{
//自己處理VIEWSTATE
base.LoadViewState (savedState);
}