此樣本示範如何建立一個名為 IndexButton 的自訂控制項,該控制項使用控制項狀態在多個頁請求間維護關鍵狀態資訊。在 ASP.NET 2.0 版中引入的控制項狀態與檢視狀態類似,但功能上獨立於檢視狀態。網頁開發人員可能會出於效能原因而禁用整個頁面或單個控制項的檢視狀態,但他們不能禁用控制項狀態。控制項狀態是專為儲存控制項的重要資料(如一個頁面控制項的頁數)而設計的,回傳時必須用到這些資料才能使控制項正常工作(即便禁用檢視狀態也不受影響)。預設情況下,ASP.NET 頁架構將控制項狀態儲存在頁的一個隱藏元素中,檢視狀態也同樣儲存在此隱藏元素中。即使禁用檢視狀態,或是使用 Session 管理狀態時,頁面中的控制項狀態仍會傳輸至用戶端,然後返回到伺服器。在回傳時,ASP.NET 會對隱藏元素的內容進行還原序列化,並將控制項狀態載入到每個註冊過控制項狀態的控制項中。
| 注意 |
請僅對那些在回傳過程中對控制項至關重要的少量關鍵資料使用控制項狀態,而不要將控制項狀態作為檢視狀態的備用選項使用。 |
此樣本闡釋了一個同時在控制項狀態和檢視狀態中儲存狀態的自訂控制項。在此樣本中,IndexButton 控制項派生自 Button 類,還定義了一個 Index 屬性,並將該屬性儲存在控制項狀態中。為了進行比較,IndexButton 還定義了一個 IndexInViewState 屬性,該屬性儲存區在 ViewState 字典中。為了瞭解控制項狀態和檢視狀態之間的差異,請使用本主題後面的“IndexButton 控制項的測試頁”一節中列出的 .aspx 頁來示範 IndexButton 控制項。
IndexButton 控制項的代碼清單
VB
C#C++F#JScript複製
// IndexButton.csusing System;using System.ComponentModel;using System.Security.Permissions;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace Samples.AspNet.CS.Controls{ [ AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal), ToolboxData("<{0}:IndexButton runat=/"server/"> </{0}:IndexButton>") ] public class IndexButton : Button { private int indexValue; [ Bindable(true), Category("Behavior"), DefaultValue(0), Description("The index stored in control state.") ] public int Index { get { return indexValue; } set { indexValue = value; } } [ Bindable(true), Category("Behavior"), DefaultValue(0), Description("The index stored in view state.") ] public int IndexInViewState { get { object obj = ViewState["IndexInViewState"]; return (obj == null) ? 0 : (int)obj; } set { ViewState["IndexInViewState"] = value; } } protected override void OnInit(EventArgs e) { base.OnInit(e); Page.RegisterRequiresControlState(this); } protected override object SaveControlState() { // Invoke the base class's method and // get the contribution to control state // from the base class. // If the indexValue field is not zero // and the base class's control state is not null, // use Pair as a convenient data structure // to efficiently save // (and restore in LoadControlState) // the two-part control state // and restore it in LoadControlState. object obj = base.SaveControlState(); if (indexValue != 0) { if (obj != null) { return new Pair(obj, indexValue); } else { return (indexValue); } } else { return obj; } } protected override void LoadControlState(object state) { if (state != null) { Pair p = state as Pair; if (p != null) { base.LoadControlState(p.First); indexValue = (int)p.Second; } else { if (state is int) { indexValue = (int)state; } else { base.LoadControlState(state); } } } } }}代碼討論
IndexButton 控制項的實現闡釋了三個任務,必須執行這三個任務才能使控制項參與控制項狀態:
重寫 OnInit 方法並調用 RegisterRequiresControlState 方法向頁面註冊,以參與控制項狀態。必須針對每個請求完成此任務。
重寫 SaveControlState 方法,以在控制項狀態中儲存資料。
重寫 LoadControlState 方法,以從控制項狀態載入資料。此方法調用基類方法,並擷取基類對控制項狀態的基值。如果 indexValue 欄位不為零,而且基類的控制項狀態也不為空白,Pair 類便可作為方便的資料結構使用,用來儲存和還原由兩部分組成的控制項狀態。
IndexButton 控制項的測試頁
下面的樣本闡釋一個頁面,該頁通過在 @ Page 指令中將 EnableViewState 屬性設定為 false 來禁用檢視狀態。該頁使用 IndexButton 控制項,並在 Page_Load 事件處理常式中,將控制項的 Index 和 IndexInViewState 屬性的值加 1。頁中的標籤顯示 Index 和 IndexInViewState 兩個屬性的值。
由於 Index 屬性儲存區在無法停用控制項狀態中,因而 Index 屬性會在回傳時維護其值,並在每次將頁回傳到伺服器時加 1。相比之下,因為 IndexInViewState 屬性儲存區在檢視狀態中,而頁的檢視狀態已被禁用,所以 IndexInViewState 屬性始終為預設值零。
VB
C#C++F#JScript複製
<%@ Page Language="C#" Trace="true" EnableViewState="false" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><script runat="server"> void Page_Load(object sender, EventArgs e) { Label1.Text = (IndexButton1.Index++).ToString(); Label2.Text = (IndexButton1.IndexInViewState++).ToString(); }</script><html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>IndexButton test page</title> </head> <body> <form id="form1" runat="server"> Click the button: <aspSample:IndexButton Text="IndexButton" ID="IndexButton1" runat="server"/> <br /> <br /> The value of the Index property of IndexButton is:<br /> <asp:Label ID="Label1" Runat="server" Text="Label"> </asp:Label> <br /> <br /> The value of the IndexInViewState property of IndexButton is: <br /> <asp:Label ID="Label2" Runat="server" Text="Label"> </asp:Label> <br /> </form> </body></html>