在 ASP.NET 2.0 之前,開發自訂伺服器控制項時,若需跨回傳保留關鍵狀態(如 GridView 的分頁索引、TabContainer 的作用中索引標籤),唯一選擇是 ViewState。然而 ViewState 可在頁面或控制項層級被關閉(EnableViewState="false"),一旦關閉,控制項核心功能將失效。為解決此痛點,ASP.NET 2.0 引入 控制項狀態——不可被關閉、專供控制項內部使用、不佔用頁面層級 ViewState 配額的狀態持久化機制。
| 特性 | 視圖狀態 | 控制項狀態 |
|---|---|---|
| 可被關閉 | 是 | 否 |
| 作用範圍 | 頁面/控制項 | 僅控制項 |
| 儲存位置 | __VIEWSTATE 隱藏欄位 | __VIEWSTATE 或獨立隱藏欄位 |
| 序列化優化類型 | 基本型別、集合、TypeConverter | 同上,預設支援更廣 |
| 生命週期事件 | SaveViewState / LoadViewState | SaveControlState / LoadControlState |
| 執行順序 | 較晚 | 優於 ViewState |
控制項狀態預設支援:Array、DateTime、Int16/32、String、ArrayList、Double、Boolean、Enum、Byte、Hashtable、Pair、Triplet、Char、HybridDictionary、Single、Type、Color、IDictionary 等,並可透過 TypeConverter 擴展自訂型別。
OnInit 中呼叫 Page.RegisterRequiresControlState(this)。SaveControlState,回傳需持久化的物件(通常為非預設值)。LoadControlState(object state),還原儲存的物件。public class SmartTabControl : WebControl {
private int _activeTabIndex = 0;
protected override void OnInit(EventArgs e) {
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
protected override object SaveControlState() {
return _activeTabIndex != 0 ? (object)_activeTabIndex : null;
}
protected override void LoadControlState(object savedState) {
if (savedState != null) _activeTabIndex = (int)savedState;
}
// 渲染邏輯略...
}
PageIndex、SortExpression、SortDirection,確保使用者關閉 ViewState 仍能正常分頁排序。EnableViewStateMAC 與加密,適合儲存非敏感但關鍵的 UI 狀態。SaveControlState 僅回傳非預設值,減少隱藏欄位體積。TypeConverter。EnableViewState="false" 驗證控制項核心功能完整。控制項狀態是 ASP.NET 2.0 為解決「ViewState 可被關閉導致控制項失效」而設計的關鍵機制。掌握 RegisterRequiresControlState、SaveControlState、LoadControlState 三要素,能讓你開發出更健壯、可重用的伺服器控制項,在任何 ViewState 設定下都能正常運作。