上篇文章寫到ASP.NET頁面的生命週期。詳見:http://www.cnblogs.com/zhaozhan/archive/2009/06/21/1507740.html。
Page_PreInit事件來執行以下操作:檢查IsPostBack屬性來確定是不是第一次處理該頁,建立或重新建立動態控制項,動態設定主控頁,動態設定Theme屬性,讀取或設定設定檔的屬性值。如果請求回傳請求,則空間的值尚未從檢視狀態還原,如果在此階段設定控制項屬性,則其值可能在下一時間中被重寫。
Page_Init事件中所有的控制項都設為預設的狀態,但此時檢視狀態沒有被恢複。這意味著Page_Init不應該用來處理伺服器控制項的值和狀態。
InitComplete事件由Page對象引發。使用該事件來處理要求先完成所有初始化工作的任務。
Page_PreLoad:如果需要在Load事件之前對頁或控制項執行處理使用。在Page引發該事件後,它會為自身和所有控制項載入檢視狀態,然後會處理Request執行個體包括的任何回傳資料。
Page_Load事件是ASP.NET編程中最常用的時間。它在Page_Init事件之後調用。Page_Load事件和Page_Init事件之間的主要差別是到觸發Page_Load事件時。所有的伺服器空間的檢視狀態都將被恢複。這使得該時間可以很理想地用於操縱空間並準備頁面的內容,然後再呈現給用戶端。
控制項事件在頁面初始化階段之後進行處理。來處理特定控制項的事件,如Button控制項的Click事件或TextBox控制項的TextChanged事件。在回傳請求中,如果頁包含驗證程式控制項,請在執行任何處理之前Page和各個驗證控制項的IsValid屬性。
LoadComplete事件來處理載入頁面上的所有其他控制項的任務。
PreRender事件對頁或其空間的內容進行最後的更改。
SaveStateComplete:在該事件發生前,已針對頁和所有控制項儲存了ViewState。將忽略此時對頁或控制項進行的任何更改。
使用該事件執行滿足以下條件的任務:要求已經儲存了檢視狀態,但未對控制項進行任何更改。
Render:這不是事件;在處理的這個階段,Page對象會在每個控制項上調用此方法。所有 ASP.NET Web 伺服器控制項都有一個用於寫出發送給瀏覽器的控制項標記的Render方法。如果建立自訂控制項,通常要重寫此方法以輸出控制項的標記。不過,如果自訂控制項只合并標準的 ASP.NET Web 伺服器控制項,不合并自訂標籤,則不需要重寫Render方法。使用者控制項(.ascx 檔案)自動合并呈現,因此不需要在代碼中顯式呈現該控制項。
UnLoad事件首先針對每個控制項發生,繼而針對該頁發生。在控制項中,使用該事件對特定控制項執行最後清理,如關閉控制項特定資料庫連接。
對於頁自身,使用該事件來執行最後清理工作,如:關閉開啟的檔案和資料庫連接,或完成日誌記錄或其他請求特定任務。在卸載階段,頁及其控制項已被呈現,因此無法對響應流做進一步更改。如果嘗試調用方法(如Response.Write 方法),則該頁將引發異常。
下面做個簡單的Demo:
在下面的例子,建立一個投票的Web表單,允許使用者投票選擇喜愛的顏色。
<form id="form1" runat="server"> <div style=" color:Maroon; font-size:5; font-weight:bold;"> <h2>Vote For Your Favorite Color!</h2> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" BorderColor="#DEDA84" BorderStyle="None" CellPadding="3" CellSpacing="2" BorderWidth="1px" BackColor="#DEBA84"> <SelectedRowStyle Font-Bold="true" ForeColor="White" BackColor="#738A9C" /> <RowStyle ForeColor="#8C4510" BorderColor="#FFF7E7" /> <HeaderStyle Font-Bold="true" ForeColor="White" BackColor="#A55129"/> <FooterStyle ForeColor="#8C4510" BackColor="#F7DFB5" /> <Columns> <asp:BoundField DataField="Key" HeaderText="Name" /> <asp:BoundField DataField="Value" HeaderText="# of Votes" /> <asp:ButtonField Text="Vote" ButtonType="Button" HeaderText="Vote" CommandName="Vote" /> </Columns> </asp:GridView> </div> <asp:Button ID="btnReset" runat="server" Text="Reset Votes" /> </form>
在Page_Load事件中:或者把所有的投票數設為初始的零值,或者從應用程式的緩衝中檢索投票數。
protected Hashtable VoteTally; protected string[] ColorList = { "Red","Green","Blue","Black","White"}; protected void Page_Load(object sender, EventArgs e) { VoteTally = new Hashtable(); foreach (string strKey in ColorList) { if (Cache.Get(strKey) == null) VoteTally.Add(strKey, 0); else VoteTally.Add(strKey, Cache.Get(strKey)); } }
在頁面卸載時,把這些值緩衝起來,是頁面的所有其他使用者也能投票。
protected void Page_UnLoad(object sender, EventArgs e) { foreach (string strKey in ColorList) { Cache.Insert(strKey, VoteTally[strKey]); } }
當使用者點擊某一行的命令按鈕投票選擇一種顏色時,觸發RowComand。這是一個事件起泡(event bubbling),容器控制項中的一個子控制項引起容器控制項的一個事件被觸發。控制項事件是在Page_Load事件觸發之後觸發的。
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName == "Vote") { int id = Convert.ToInt32(e.CommandArgument); string strKey = GridView1.Rows[id].Cells[0].Text.ToString(); VoteTally[strKey] =(int) VoteTally[strKey] + 1; } }
在Page_PreRender事件期間把資料來源綁定到GridView。在PreRender事件綁定的好處是可以清除兩次綁定資料的情況(一次在Page_Load中,一次在RowComand中),通過把綁定放到Page_PreRender中,只需把綁定資料的代碼放到一個地方,它可以覆蓋所有的情況。
private void Page_PreRender(object sender, EventArgs e) { GridView1.DataSource = VoteTally; GridView1.DataBind(); }
清除所有的緩衝。重新投票計數。
protected void btnReset_Click(object sender, EventArgs e) { foreach (string strKey in ColorList) { VoteTally[strKey] = 0; Cache.Insert(strKey, 0); } }
頁面的顯示效果如下:
在Global.asax設定Application_BeginRequest和Application_EndRequest方法。統計頁面時間。
void Application_BeginRequest(object sender, EventArgs e) { Application[Request.UserHostAddress.ToString()] = DateTime.Now; } void Application_EndRequest(object sender, EventArgs e) { DateTime sTime = (DateTime)Application[Request.UserHostAddress.ToString()]; Application.Remove(Request.UserHostAddress.ToString()); Response.Write("<hr/>"); Response.Write("Total Page Processing Time="); Response.Write((DateTime.Now.Ticks-sTime.Ticks)/1000000.0); Response.Write("Seconds"); }