在 ASP.NET 中,控制項的屬性與 ViewState 有著密不可分的關係,透過 ViewState 才有辨法維護控制項的屬性值。在本文中將介紹屬性與 ViewState 的關係,並說明屬性如何存取 ViewState 是比較有效率的方式。
當你加入一個「ASP.NET 伺服器控制項」時,類別中預設會有一個 Text 屬性寫法的範例如下所示,屬性的讀寫都是直接存取 ViewState,這是一般常見的控制項屬性寫法。可是這種屬性的寫法是沒有效率的,因為 ViewState 的成員是 Object 型別,每次讀取屬性時都是由 ViewState 取出指定鍵值的成員再轉型為屬性的型別,寫入屬性的動作也是直接寫入 ViewState 中。
Property Text() As String
Get
Dim s As String = CStr(ViewState("Text"))
If s Is Nothing Then
Return String.Empty
Else
Return s
End If
End Get
Set(ByVal Value As String)
ViewState("Text") = Value
End Set
End Property
比較好的方式應該是讀取 ViewState 成員只做一次型別轉換的動作,而寫入 ViewState 的動作可以在 Render 前做批次寫入的動作即可。為了達到這樣的需求,我們可以覆寫 LoadViewState 及 SaveViewState 方法來處理屬性與 ViewState 的存取動作;當控制項初始化後會執行 LoadViewState 方法,來載入 ViewState 還原的控制項狀態,當控制項 Render 之前,會執行 SaveViewState 方法,將控制項的最終狀態存入 ViewState 中,也就是在此方法之後對控制項所做的任何變更都將會被忽略。
我們改寫屬性的寫法,不直接用 ViewState 來存取屬性,而是改用「屬性區域變數」來存取屬性,在 LoadViewState 時載入 ViewState 到屬性區域變數,而 SaveViewState 時再將屬性區域變數寫入 ViewState 中。我們依此方式將 Text 屬性改寫如下。
Private FText As String
Property Text() As String
Get
Return FText
End Get
Set(ByVal Value As String)
FText = Value
End Set
End Property
''' <summary>
''' 載入 ViewState 還原控制項狀態。
''' </summary>
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
If Not (savedState Is Nothing) Then
' Load State from the array of objects that was saved at vedViewState.
Dim myState As Object() = CType(savedState, Object())
If Not (myState(0) Is Nothing) Then
MyBase.LoadViewState(myState(0))
End If
If Not (myState(1) Is Nothing) Then
FText = CType(myState(1), String)
End If
End If
End Sub
''' <summary>
''' 將控制項狀態寫入 ViewState 中。
''' </summary>
Protected Overrides Function SaveViewState() As Object
Dim baseState As Object = MyBase.SaveViewState()
Dim myState(1) As Object
myState(0) = baseState
myState(1) = FText
Return myState
End Function
利用上述的方式,我們可以在 LoadViewState 批次載入所有屬性值,而在 SaveViewState 批次寫入屬性值,如此在讀取屬性就不用一直做型別轉換的動作以改善效率。
結語
雖然屬性一般都是儲存於 ViewState 中,不過若是一些無關緊要的屬性或是完全不會執行階段就變更的屬性,可以考慮不需要將這些屬性儲存於 ViewState 中;因為 ViewState 是個兩面刃,ViewState 可以很輕易幫我們維護屬性值,不過相對的也增加了面頁的傳輸量,所以可以視實際情形來決定屬性是否要儲存於 ViewState 中。
備註:本文同步發佈於筆者「ASP.NET 魔法學院」部落格
http://www.dotblogs.com.tw/jeff377/archive/2008/10/07/5601.aspx