asp.net生命周期:
ASP.NET 頁運行時,此頁將經歷一個生命周期,在生命周期中將執行一系列處理步驟。這些步驟包括初始化、實例化控件、還原和維護狀態、運行事件處理程序代碼以及進行呈現。了解頁的生命周期非常重要,這樣就能在合適的生命周期階段編寫代碼,以達到預期效果。此外,如果開發自定義控件,則必須熟悉頁生命周期,從而正確地初始化控件,使用視圖狀態數據填充控件屬性以及運行所有控件行為邏輯。(控件的生命周期基於頁的生命周期,但是頁引發的控件事件比單獨的 ASP.NET 頁中可用的事件多。)

常規頁生命周期階段

一般來說,頁要經歷下表概述的各個階段。除了頁生命周期階段以外,還有在請求前后出現的應用程序階段,但是這些階段並不特定於頁。有關更多信息,請參見 ASP.NET 應用程序生命周期概述

 
階段 說明

頁請求

頁請求發生在頁生命周期開始之前。用戶請求頁時,ASP.NET 將確定是否需要分析和編譯頁(從而開始頁的生命周期),或者是否可以在不運行頁的情況下發送頁的緩存版本以進行響應。

開始

在開始階段,將設置頁屬性,如 RequestResponse。在此階段,頁還將確定請求是回發請求還是新請求,並設置 IsPostBack 屬性。此外,在開始階段期間,還將設置頁的 UICulture 屬性。

頁初始化

頁初始化期間,可以使用頁中的控件,並將設置每個控件的 UniqueID 屬性。此外,任何主題都將應用於頁。如果當前請求是回發請求,則回發數據尚未加載,並且控件屬性值尚未還原為視圖狀態中的值。

加載

加載期間,如果當前請求是回發請求,則將使用從視圖狀態和控件狀態恢復的信息加載控件屬性。

驗證

在驗證期間,將調用所有驗證程序控件的 Validate 方法,此方法將設置各個驗證程序控件和頁的 IsValid 屬性。

回發事件處理

如果請求是回發請求,則將調用所有事件處理程序。

呈現

在呈現期間,視圖狀態將被保存到頁,然后頁將調用每個控件,以將其呈現的輸出提供給頁的 Response 屬性的 OutputStream

卸載

完全呈現頁、將頁發送至客戶端並准備丟棄時,將調用卸載。此時,將卸載頁屬性(如 ResponseRequest)並執行清理。

生命周期事件

在頁生命周期的每個階段中,頁將引發可運行您自己的代碼進行處理的事件。對於控件事件,通過以聲明方式使用屬性(如 onclick)或以使用代碼的方式,均可將事件處理程序綁定到事件。

頁還支持自動事件連接,即,ASP.NET 將尋找具有特定名稱的方法,並在引發特定事件時自動運行這些方法。如果 @ Page 指令的 AutoEventWireup 屬性設置為 true(或者如果未定義該屬性,因為默認情況下為 true),頁事件將自動綁定至使用 Page_event 命名約定的方法,如 Page_LoadPage_Init。有關自動事件連接的更多信息,請參見 ASP.NET Web 服務器控件事件模型

下表列出了最常用的頁生命周期事件。實際的事件比列出的事件要多。但是,它們不用於大多數頁處理方案。而是主要由 ASP.NET 網頁上的服務器控件使用,以初始化和呈現它們本身。如果要編寫自己的 ASP.NET 服務器控件,則需要詳細了解這些階段。有關創建自定義控件的信息,請參見開發自定義 ASP.NET 服務器控件

 
頁事件 典型使用

Page_PreInit

  • 使用 IsPostBack 屬性確定是否是第一次處理該頁。

  • 創建或重新創建動態控件。

  • 動態設置主控頁。

  • 動態設置 Theme 屬性。

  • 讀取或設置配置文件屬性值。

    Note注意

    如果請求是回發請求,則控件的值尚未從視圖狀態還原。如果在此階段設置控件屬性,則其值可能會在下一階段被改寫。

Page_Init

  • 讀取或初始化控件屬性。

Page_Load

  • 讀取和更新控件屬性。

Control events

執行特定於應用程序的處理:

  • 如果頁包含驗證程序控件,請在執行任何處理之前檢查頁和各個驗證控件的 IsValid 屬性。

  • 處理特定事件,如 Button 控件的 Click 事件。

Page_PreRender

  • 對頁的內容進行最后更改。

Page_Unload

執行最后的清理工作,可能包括:

  • 關閉打開的文件和數據庫連接。

  • 完成日志記錄或其他特定於請求的任務。

    Note注意

    在卸載階段,頁及其控件已被呈現,因此無法對響應流做進一步更改。如果嘗試調用方法(如 Response.Write 方法),則該頁將引發異常。

  1 using System.Data;
2 using System.Configuration;
3 using System.Web;
4 using System.Web.Security;
5 using System.Web.UI;
6 using System.Web.UI.WebControls;
7 using System.Web.UI.WebControls.WebParts;
8 using System.Web.UI.HtmlControls;
9
10 public partial class _Default : Page
11 {
12 #region OnPreInit 第一步
13 protected override void OnPreInit(EventArgs e)
14 {
15 //檢查 IsPostBack 屬性來確定是不是第一次處理該頁。
16 //創建或重新創建動態控件。
17 //動態設置主控頁。
18 //動態設置 Theme 屬性。
19 //讀取或設置配置文件屬性值。
20 //注意
21 //如果請求是回發請求,則控件的值尚未從視圖狀態還原。如果在此階段設置控件屬性,則其值可能會在下一事件中被重寫。
22 base.OnPreInit(e);
23 }
24 #endregion
25
26 #region OnInit 第二步
27 protected override void OnInit(EventArgs e)
28 {
29 //在所有控件都已初始化且已應用所有外觀設置后引發。使用該事件來讀取或初始化控件屬性。
30 base.OnInit(e);
31 }
32 #endregion
33
34 #region OnInitComplete 第三步
35 protected override void OnInitComplete(EventArgs e)
36 {
37 //由 Page 對象引發。使用該事件來處理要求先完成所有初始化工作的任務。
38
39 base.OnInitComplete(e);
40 }
41 #endregion
42
43 #region PreLoad 第四步
44 protected override void OnPreLoad(EventArgs e)
45 {
46 //html服務器控件的值在次恢復(值已經恢復)
47 //如果需要在 Load 事件之前對頁或控件執行處理,請使用該事件。
48 //在 Page 引發該事件后,它會為自身和所有控件加載視圖狀態,然后會處理 Request 實例包括的任何回發數據。
49 base.OnPreLoad(e);
50 }
51 #endregion
52
53 #region OnLoad 第五步
54 protected override void OnLoad(EventArgs e)
55 {
56 //Page 在 Page 上調用 OnLoad 事件方法,然后以遞歸方式對每個子控件執行相同操作,
57 //如此循環往復,直到加載完本頁和所有控件為止。
58 //使用 OnLoad 事件方法來設置控件中的屬性並建立數據庫連接。
59 base.OnLoad(e);
60 }
61 #endregion
62
63 #region 第六步
64 protected void Page_Load(object sender, EventArgs e)
65 {
66 //這個還要我說什么么?地球人都知道
67    //執行完之后,再執行用戶控件的Page_Load()事件
68 }
69 #endregion
70
71 #region 控件事件 第七步
72 protected void Button1_Click(object sender, EventArgs e)
73 {
74 //用這些事件來處理特定控件事件,如 Button 控件的 Click 事件或 TextBox 控件的 TextChanged 事件。
75 //注意
76 //在回發請求中,如果頁包含驗證程序控件,請在執行任何處理之前檢查 Page 和各個驗證控件的 IsValid 屬性。
77 }
78 #endregion
79
80 #region OnLoadComplete 第八步
81 protected override void OnLoadComplete(EventArgs e)
82 {
83 //對需要加載頁上的所有其他控件的任務使用該事件。
84
85 base.OnLoadComplete(e);
86 }
87 #endregion
88
89 #region OnPreRender 第九步
90 protected override void OnPreRender(EventArgs e)
91 {
92 //在該事件發生前:
93 //Page 對象會針對每個控件和頁調用 EnsureChildControls。
94 //設置了 DataSourceID 屬性的每個數據綁定控件會調用 DataBind 方法。
95 //有關更多信息,請參見下面的數據綁定控件的數據綁定事件。
96 //頁上的每個控件都會發生 PreRender 事件。使用該事件對頁或其控件的內容進行最后更改。
97
98 base.OnPreRender(e);
99 }
100 #endregion
101
102 #region SaveStateComplete 第十步
103 protected override void OnSaveStateComplete(EventArgs e)
104 {
105 //在該事件發生前,已針對頁和所有控件保存了 ViewState。將忽略此時對頁或控件進行的任何更改。
106 //使用該事件執行滿足以下條件的任務:要求已經保存了視圖狀態,但未對控件進行任何更改。
107
108 base.OnSaveStateComplete(e);
109 }
110 #endregion
111
112 #region Render 第十一步
113 //Render
114 //這不是事件;在處理的這個階段,Page 對象會在每個控件上調用此方法。
115 //所有 ASP.NET Web 服務器控件都有一個用於寫出發送給瀏覽器的控件標記的 Render 方法。
116 //如果創建自定義控件,通常要重寫此方法以輸出控件的標記。
117 //不過,如果自定義控件只合並標准的 ASP.NET Web 服務器控件,不合並自定義標記,則不需要重寫 Render 方法。
118 //有關更多信息,請參見開發自定義 ASP.NET 服務器控件。
119 //用戶控件(.ascx 文件)自動合並呈現,因此不需要在代碼中顯式呈現該控件。
120
121 #endregion
122
123 #region OnUnload 第十二步
124 protected override void OnUnload(EventArgs e)
125 {
126 //該事件首先針對每個控件發生,繼而針對該頁發生。在控件中,使用該事件對特定控件執行最后清理,
127 //如關閉控件特定數據庫連接。
128 //對於頁自身,使用該事件來執行最后清理工作,如:關閉打開的文件和數據庫連接,或完成日志記錄或其他請求特定任務。
129 //注意
130 //在卸載階段,頁及其控件已被呈現,因此無法對響應流做進一步更改。
131 //如果嘗試調用方法(如 Response.Write 方法),則該頁將引發異常。
132
133
134 base.OnUnload(e);
135 }
136 #endregion
137 }

 

母版頁和內容頁的執行順序:

母版頁中控件的Init->內容頁控件的Init->母版頁的Init->內容頁的Init
->內容頁的Load->母版頁的Load->內容頁中控件的Load
->內容頁的PreRender->母版頁的PreRender->母版頁控件的PreRender->內容頁中控件的PreRender

其他的頁生命周期注意事項

請注意有關頁生命周期的以下附加信息:

  • 各個 ASP.NET 服務器控件都有自己的生命周期,該生命周期與頁生命周期類似。例如,在相應的頁事件期間將調用控件的 InitLoad 方法。如果頁上包含控件,則將首先調用控件的 Init 方法,然后再調用頁的 Init 方法。但是,將在調用控件的 Load 方法之前先調用頁的 Load 方法。

  • 通過處理控件的事件,可以自定義控件的外觀或內容。例如,所有的控件都將引發 InitLoadUnload 事件,但是頁開發人員通常不處理這些事件。而是通常處理特定於控件的事件,如 Button 控件的 Click 事件和 ListBox 控件的 SelectedIndexChanged 事件。在某些情況下,可能也需處理控件的 DataBindingDataBound 事件。有關更多信息,請參見各個控件的類參考主題以及開發自定義 ASP.NET 服務器控件

  • 除了處理由頁引發的事件以外,還可以重寫頁的基類中的方法。例如,可以重寫頁的 InitializeCulture 方法,以便動態設置區域性信息。注意,在使用 Page_event 語法創建事件處理程序時,將隱式調用基實現,因此無需在方法中調用它。例如,無論是否創建 Page_Load 方法,始終都會調用頁基類的 OnLoad 方法。但是,如果使用 override 關鍵字(在 Visual Basic 中為 Overrides)重寫頁的 OnLoad 方法,則必須顯式調用基方法。例如,如果在頁中重寫 OnLoad 方法,則必須調用 base.Load(在 Visual Basic 中為 MyBase.Load)以運行基實現。