網頁的生命週期列表:

網頁的生命週期列表:

PreInit (2.0)
->初始化Theme,應用MasterPage和控件Skin
->Init
->InitComplete (2.0)
->If PostBack,創建子控件並加載控件/視圖狀態
->PreLoad (2.0)
->Load
->If PostBack,則觸發服務器端事件
->LoadComplete (2.0)
->If not PostBack,則創建子控件
->PreRender
->PreRenderComplete (2.0)
->保存控件/視圖狀態
->SaveStateComplete (2.0)
->Render
->Unload

需要注意的是上圖中標註(2.0)的事件即ASP.NET 2.0中新增的事件都僅僅是Page類中可以使用,並不是像其他事件一樣可以在控件中使用。

ASP.NET 2.0中可以通過啓用(默認值爲True)AutoEventWireUp爲網頁事件創建事件處理程序,並使用隱式爲事件處理程序註冊的方法名。
以下是VS2005隱式爲各個事件添加關聯的方法:

事件 -> 方法名
Page.PreInit -> Page_PreInit
Control.Init -> Page_Init
Page.InitComplete -> Page_InitComplete
Page.PreLoad -> Page_PreLoad
Control.Load -> Page_Load
Page.LoadComplete -> Page_LoadComplete
Control.PreRender -> Page_PreRender
Control.DataBinding -> Page_DataBind
Page.PreRenderComplete -> Page_PreRenderComplete
Page.SaveStateComplete -> Page_SaveStateComplete
Control.Unload -> Page_Unload
TemplateControl.Error -> Page_Error
TemplateControl.AbortTransation -> Page_AbortTransation
TemplateControl.AbortTransation -> OnTransationAbort
TemplateControl.CommitTransation -> Page_CommitTransation
TemplateControl.CommitTransation -> OnTransationCommit

Page基類會在請求的開頭階段調用基類TemplateControl的HookUpAutomaticHandlers方法。該方法遍歷上表中所示的方法名,並使用反射在程序員的類中查找具有相同名稱和合適特徵標的方法。如果找到合適的方法,則創建一個類型合適的委託,並使用該方法初始化它,並將其加入委託列表,該委託在相應事件發生時候將被觸發。
這些事件都是由基類Page的一個虛方法或者Page類從基類Control繼承的虛方法觸發。所以可以有三種方法註冊這些事件:(以Load事件爲例)

1、顯式的將一個委託和一個事件關聯起來(通常都是在網頁的Init處理程序中)
2、編寫一個名爲Page_Load的方法,並使其特徵標和事件相同
3、重寫Override虛方法Onload

這個三個方法中重寫Override比較快一點點,但是VS2005默認是第二種。

MSDN上對Asp.net生命週期解釋有非常重要的四個表格:

protected void Page_Load(object sender, EventArgs e)
{
//create a dynamic dropdown
DropDownList d = new DropDownList();
PlaceHolder1.Controls.Add(d); // TrackViewState() gets fired for our dropdown, so state is maintained
if (!IsPostBack)
{
d.Items.Add("test1");
d.Items.Add("test2");
}
}

This will not work:


protected void Page_Load(object sender, EventArgs e)

{

//create a dynamic dropdown

DropDownList d = new DropDownList();

if (!IsPostBack)

{

d.Items.Add("test1");

d.Items.Add("test2");

}

PlaceHolder1.Controls.Add(d); //"test1" and "test2" values are lost

}

TRULY Understanding Dynamic Controls

Part 1: Dynamic vs. Static

Part 2: Creating Dynamic Controls

Part 3: Adding Dynamic Controls to the Control Tree

Part 4: Because you don't know to render at design time

Asp.net2.0頁面的生命週期

當一個獲取網頁的請求(可能是通過用戶提交完成的,也可能是通過超鏈接完成的)被髮送到Web服務器後,這個頁面就會接着運行從創建到處理完成的一系列事件。在我們試圖建立Asp.net頁面的時候,這個執行週期是不必去考慮的,那樣只會自討苦喫。然而,如果被正確的操縱,一個頁面的執行週期將是一道有效而且功能強大的工具。許多開發者在編寫 Asp.net的頁面以及用戶控件的時候發現,如果知道整個過程中發生了什麼以及在什麼時候發生將對完成整個任務起到很重要的幫助作用。下面我就向大家介紹一下一個Asp.net頁面從創建到處理完成過程中的十個事件。同時,也向大家展示如何在這些事件中添加自己的代碼以達到預定的效果。

一.預初始化對象(OnPreInit)


protected override void OnPreInit(EventArgs e)
{
// custom code
base.OnPreInit(e);
}


注意,我們只能在PreInit()事件中動態的設置themes

使用母版頁時的特例
我們先要了解一個非常重要的知識點——母版頁被處理的過程就相當於內容頁中的一個控件。

所以如果一個頁有其相關聯的母版頁的話,那麼在PreInit()事件裏頁中的所有控件都不會被初始化。而只有在Init()事件開始之後,你才能直接訪問這些控件。爲什麼?

這個原因就是內容頁中的所有控件都包含在“ContentPlaceholder”裏,而“ContentPlaceholder”其實就是母版頁的一個子控件。現在母版頁被處理的過程就相當於內容頁中的一個控件,我們早先提到過,除了Init()和Unload()之外的所有事件都是從最外面到最裏面被激發的。雖然頁的PreInit()是第一個被觸發的事件,但是用戶控件和母版頁是沒有這個事件的,所以在頁的Page_PreInit()方法中,母版頁和用戶控件都不會被初始化,而是在Init()事件之後

接下來讓我們來看一下Page_Init()事件之後控件的層次結構

在這個頁面級的事件中,所有在設計時創建的控件都將被用默認值做初始化。例如,如果你有一個Text屬性值爲“Hello”的TextBox控件,則此時這個屬性被設置。我們也可以在這裏動態的創建控件。

這個事件僅僅發生在頁級別的類中,用戶控件和母版頁沒有這個事件

下面的代碼示例瞭如何重寫這個方法以增加你的自定義代碼

二.初始化對象(OnInit)

一個頁面的控件(以及頁面本身)最初應被正確的初始化。通過在你的C#文件的構造函數中聲名所有對象,頁面就知道要創建多少對象以及它們的類型。一旦你在你的構造函數中聲名了所有的對象,你就可以通過繼承類、方法、事件或是屬性訪問它們。然而,如果你的一些對象是在Aspx文件中指定的一些控件,那麼這些控件就沒有屬性可言了。同時,通過代碼訪問它們會產生一些意外的錯誤,因爲這些控件實例是沒有一個確定的創建順序的(如果它們是被一起創建的)。還有,你可以通過OnInit來重載初始化事件.

在這個事件裏,我們能讀出控件的屬性(在設計模式中設置的)。但是我們不能讀出用戶設置的值,因爲得到用戶設置的值是在LoadPostData()事件被激發之後。不過在這個事件中我們可以得到POST數據,如下
string selectedValue = Request.Form[controlID].ToString();

三.完成初始化(OnInitComplete)

完成初始化頁面OnInit事件後觸發。


四.導入Viewstate數據(LoadViewState)


在初始化事件後,所有控件只可以通過它們的ID被引用訪問(因爲還沒有相應的DOM可使用)。在 LoadViewState這個事件中,所有的控件將獲得它們的第一個屬性:Viewstate屬性。這個屬性最終將被返回給服務器以判斷這個頁面是已經被用戶訪問完畢還是仍然在被用戶所訪問。Viewstate屬性以“名稱/值”對的字符串方式被保存,它包含了控件的文本以及值等信息。該屬性被存儲在一個隱藏的<input>控件的值屬性裏,在請求頁面時被傳遞。這種方式比起Asp3.0的維持、判斷頁面狀態的方式有了很大的進步啊。還有,你可以重載LoadViewState事件函數來對相應的控件進行值設定。下圖是一個例子:


五.用LoadPostData處理Postback數據(LoadPostData)

在頁面創建的這個階段,服務器對頁面上的控件提交的表單數據(在Asp.net中稱postback數據)進行處理。當一個頁面提交一個表單時,框架就在每個提交了數據的控件上執行一個IPostBackDataHandler接口操作。然後頁面執行LoadPostData事件,解析頁面,找到每個執行了IpostBackDataHandler接口操作的控件,並用恰當的postback數據更新這些控件狀態。Asp.net是通過用 NameValue集中的“名稱/值”對和每個控件的唯一的ID匹配來實現這一操作的。所以,在Asp.net的頁面上每個控件必須有一個唯一的ID,不可以出現幾個控件共有ID的情況。即使是用戶自定義的一些控件,框架也會賦予它們各自唯一的ID的。在LoadPostData事件後,就要執行下面的 RaisePostDataChanged事件了。

六.OnPreLoad
在加載頁面OnLoad事件前觸發。可以在頁面裏面通過Page_OnPreLoad事件綁定

七.導入對象(OnLoad)

Page_Load是事件綁定得方法
page.load + = new eventhandler(Page_Load)
OnLoad()是引發Load事件主要是判斷事件是否爲空,如果不爲空就執行事件下綁定得方法


在Load事件中,對象都實例化了。所有的對象第一次被佈置在DOM頁面(在Asp.net中稱控件樹)裏了並且可以通過代碼或是相關的位置被引用。這樣,對象就可以很容易的從客戶端獲得諸如寬度、高度、值、可見性等在Html中的屬性值。在Load事件中,當然還有像設置控件屬性等操作的發生。這個過程是整個生命週期中最重要、最主要的,你可以通過調用OnLoad來重載Load事件,圖示如下:


八.RaisePostBackChanged事件(RaisePostDataChangedEvent)


就像在上面提到的那樣,這個事件是發生在所有的控件執行了IPostBackDataHandler接口操作並被正確的 postback數據更新後的。在這個過程中,每個控件都被賦予一個布爾值來標誌該控件有沒有被更新。然後,Asp.net就在整個頁面上尋找任何已被更新過的控件並執行RaisePostDataChanged事件操作。不過,這個事件是要在所有的控件都被更新了以及Load事件完成後才進行的。這樣就保證了一個控件在被postback數據更新前,別的控件在RaisePostDataChanged事件中是不會被手動改變的。


九.處理客戶端PostBack事件(RaisePostBackEvent)


當由postback數據在服務器端引起的事件都完成後,產生postback數據的對象就執行 RaisePostBackEvent事件操作。可是會有這種情況,由於一個控件狀態的改變使得它將表單返回給服務器或是用戶點擊了提交按鈕使得表單返回給服務器。在這種情況下應該有相應的處理代碼來體現事件驅動這一面向對象(OOP)編程原則。由於要滿足呈現給瀏覽器的數據的精確性要求,在一系列 postback事件中RaisePostBackEvent事件是最後發生的。


在postback過程中改變的控件不應在執行功能函數被調用後更新。也就是說,任何由於一個預期的事件而改變的數據應該在最終的頁面上被反映出來。你可以通過修改RaisePostBackEvent函數來滿足你的要求,圖示如下:

十.Page_OnLoadComplete

完成頁面加載OnLoad事件後觸發。

十一.預先呈遞對象

可以改變對象並將改變保存的最後時刻就是這一步――預先呈遞對象。這樣,你可以在這一步對控件的屬性、控件樹結構等作出最後的修改。同時還不用考慮 Asp.net對其作出任何改變,因爲此時已經脫離了數據庫調用以及viewstate更新了。在這一步之後,對對象的所有修改將最終被確定,不能被保存到頁面的viewstate中了。你可以通過OnPreRender來重載這一步。

十二.完成預呈現(OnPreRenderComplete)

在完成預呈現OnPreRender事件後觸發。這是完成頁面呈現的最後一道關卡,在此之後,頁面將無法再進行任何呈現上的改動。

十三.保存ControlState(SaveControlState)
保存控件狀態ControlState。ControlState是ASP.NET2.0控件新增的一個屬性,類似ViewState作用,但它們區別在於 ControlState用於保存更加重要的控件狀態信息,以保證在禁用ViewState的情況下還可以對控件狀態進行讀寫操作。


八.保存ViewState(SaveViewState)


所有對頁面控件的修改完成後viewstate就被保存了。對像的狀態數據還是保留在隱藏的<input> 控件裏面,呈現給Html的對象狀態數據也是從這裏取得的。在SaveViewState事件中,其值能被保存到viewstate對象,然而這時在頁面上控件的修改卻不能了。你可以用SaveViewState來重載這一步,圖示如下:


九.呈遞給Html(Render)


運用Html創建給瀏覽器輸出的頁面的時候Render事件就發生了。在Render事件過程中,頁面調用其中的對象將它們呈遞給Html。然後,頁面就可以以Html的形式被用戶的瀏覽器訪問了。當Render事件被重載時,開發者可以編寫自定義的Html代碼使得原先生成的Html都無效而按照新的Html來組織頁面。Render方法將一個HtmlTextWriter對象作爲參數並用它將Html在瀏覽器上以網頁的形式顯示。這時仍然可以做一些修改動作,不過它們只是客戶端的一些變化而已了。你可以重載Render事件,圖示如下:


十.銷燬對象(Page_UnLoad)


在呈遞給Html完成後,所有的對象都應被銷燬。在Dispose事件中,你應該銷燬所有在建立這個頁面時創建的對象。這時,所有的處理已經完畢,所以銷燬任何剩下的對象都是不會產生錯誤的,包括頁面對象。你可以重載Dispose事件。


全文總結

以上就是Asp.net頁面生命週期中的幾個主要事件。每次我們請求一個Asp.net頁面時,我們都經歷着同樣的過程:從初始化對象到銷燬對象。通過了解Asp.net頁面的內部運行機制,我相信大家在編寫、調試代碼的時候會更加遊刃有餘的。不過整個頁面的生命週期的方法如下:


查看頁面生命週期的底層細節,我們可以看到 ASP.NET 2.0 中提供的許多功能(例如主題和個性化)將在什麼地方容易實現。例如,主題在 IntializeThemes 事件中處理,而個性化數據將在 LoadPersonalizationData 中加載並稍後用於 ApplyPersonalization 方法。請注意,就哪一個 UI 元素將決定 Web 應用程序的最終外觀和感覺而言,方法的順序非常重要。

AspNet2.0頁面生命週期

頁面框架通過如下過程處理aspx文件請求:
1:解析aspx文件,並創建一個控件樹;
2:使用控件樹動態實現一個繼承自Page類的類或者控件 ;
3:動態編譯類;
4:緩存編譯類,以備後用;
5:動態創建一個編譯類的實例。頁面開始啓動生命期,在這個過程中,頁面將通過生命週期的不同階段;=========================================================
頁面經歷瞭如下階段【其中一些階段標記爲僅僅回傳,是說只有在被回傳到服務器時,頁面才經歷這些階段】:

01:頁面首先從QueryString或者Request對象的Form集合中獲得回傳數據。

02:頁面檢測回傳數據集合(NameValueCollection,Form或者QueryString)是否包含一個鍵爲_CallBackId的項。如果存在,那麼設置其Boolean屬性IsCallBack爲True,以便通過AspNet客戶端回調機制,標明頁面已經回傳到服務器。

03:預初始化(PreInit):
在頁面生命週期的預初始化階段執行如下操作:
a:調用OnPreInit方法引發PreInit事件。
b:利用App_Themes目錄中的內容初始化主題,以動態實現一個PageTheme類型的類,
編譯該類,並創建一個編譯類的實例,接着將實例賦值給它的PageTheme屬性值
c:應用母版頁

04:初始化(Init):
在頁面生命週期的初始化階段執行以下操作
a:遞歸初始化Controls集合中的控件。初始化包括設置這些控件的屬性,
例如:Page,Id和NameContainer等
b:遞歸應用控件皮膚
c:調用OnInit方法以引發自身的Init事件,接着遞歸調用子控件的OnInit方法來引發它們的Init事件
d:調用自身的TrackViewState方法來啓動自身的視圖狀態跟蹤,接着遞歸調用子控件
的TrackViewState方法來啓動它們的視圖狀態跟蹤。

05:完成初始化(InitComplete):
頁面調用OnInitComplete方法來引發InitComplete事件。該事件標明瞭初始化階段的結束。
此時,頁面Controls集合的所有控件都被初始化了。


06:加載控件狀態(Load Control State)[PostBack Only]:
頁面遞歸調用Control集合中控件的LoadControlState方法,這些控件已經調用了Page類
的RegisterRequiresControlState方法,以使用它們的控件狀態。

07:加載視圖狀態(Load View State)[PostBack Only]:
頁面首先調用自身的LoadViewState方法,接着遞歸調用Controls集合控件的LoadViewState方法,以允許它們加載它們的已經保存的視圖狀態。

08:加載回傳數據(Load Post Data)[PostBack Only]:
頁面調用實現IPostBackDataHandler接口的控件的LoadPostData方法,並將回傳數據傳遞給該方法。每個控件的LoadPostDate方法都必須訪問回傳數據,並據此更新相應的控件屬性。
例如:TextBox控件的LoadPostData方法將文本框的新值設置爲TextBox控件的Text屬性值。

09:預加載(PreLoad):
頁面調用OnPreLoad方法以引發PreLoad事件。該事件表示頁面生命週期將進入加載階段。

10:加載(Load):
頁面首先調用自身的OnLoad方法以引發自身的Load事件,接着遞歸調用Controls集合中控件的OnLoad方法以引發它們的Load事件。頁面開發人員可以爲Load事件註冊回調,那麼就可以通過編程將子控件添加到頁面的Controls集合中。

11:加載回傳數據(Load Post Data)[PostBack Only Second Try]:
頁面調用控件的LoadPostBack方法。這些控件如果實現了IPostBackDataHandler接口,那麼在加載階段,它們已通過編程添加到Controls集合中。

12:引發回傳數據修改事件(Raise Post Data Changed Event)[PostBack Only]:
頁面調用控件的RaisePostDataChangeEvent方法,這些控件的LoadPostData方法返回true。
RaisePostDataChangeEvent方法引發了回傳數據修改事件。例如:當文本框的新值與舊值
不同時,那麼TextBox控件將引發該事件。

13:引發回傳事件(Raise PostBack Event)[PostBack Only]:
頁面調用控件的RaisePostEvent方法,這些控件相關的Html元素用於提交表單。例如,Button控件的相關Html元素將頁面回傳到服務器。控件的RaisePostBackEvent方法必須將回傳事件映射到一個或多個服務器事件。例如,Button控件的 RaisePostBackEvent方法將事件映射到了服務器端事件Command和Click上。

14:完成加載(Load Complete):
頁面調用OnLoadComplete方法來引發LoadComplete事件,這表示所有加載活動,包括加載回傳數據,以及引發回傳數據修改事件,並以更新控件自身的活動都完成了。

15:引發回調事件(Raise CallBack Event)(PostBack And CallBack Only):
頁面調用控件的RaiseCallBackEvent方法。該控件可使用AspNet客戶端回調機制來允許客戶端方法(例如JavaScript函數)調用服務器端方法,而無需將整個頁面回傳給服務器。
RaiseCallBackEvent方法必須調用服務器端方法。如果頁面的回傳使用了客戶端回調機制,那麼頁面將不會執行剩餘的頁面生命週期階段。

16:預呈現(PreRender):
在頁面生命週期這個階段執行一下操作。
a:調用EnsureChildControls方法來確保在頁面進入呈現階段之前,創建其子控件。
b:調用自身的OnPreRender方法來引發PreRender事件。
c:遞歸調用Controls集合中控件的OnPreRender方法,以引發它們的PreRender事件。

17:預呈現完成(PreRender Complete):
頁面調用OnPrerenderComplete方法來引發PreRenderComplete事件,這表示所有預呈現活動完成了。

18:保存控件狀態(Save Control State):
頁面遞歸調用Controls集合中控件的SaveControlState方法。這些控件已經調用了Page類的RegisterRequiresControlState方法來保存它們的控件狀態。

19:保存視圖狀態(Save View State):
頁面首先調用自身的SaveViewState方法,然後調用Controls集合中的SaveViewState方法,以允許它們來保存其視圖狀態。

20:保存狀態完成(Save View Complete):
頁面調用OnSaveStateComplete方法以引發SaveStateComplete事件,這表示所有狀態保存活動都完成了。

21:呈現:
在頁面生命週期的這個階段執行一下操作。
a:創建一個HtmlTextWriter類實例,該實例封裝了輸出響應流
b:調用RenderCOntrol方法,並將HtmlTextWriter實例傳遞給該方法。
RenderControl方法遞歸調用子控件的RenderControl方法,以便允許每個控件能夠呈現其
Html標記文本。子控件的Html標記文本組成了最終發送給客戶端瀏覽器的Html標記文本。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章