在 Page Init 事件中動態建立的控制項有辨法自行維護狀態,因為這些控制項在 PostBack 後會執行 LoadViewState 來還原控制項的狀態。不過我們來看一個案例,首先在頁面上放置一個 Button 做 PostBack 使用,然後在程式碼中 Page Init 事件中動態建立一個 Literal 控制項,並在頁面第一次執行時(判斷 Not IsPostBack) 設定 Literal.Text 初始值,然後把這個 Literal 控制項加入頁面。
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Dim oLiteral As New Literal()
If Not Me.IsPostBack Then
oLiteral.Text = "初始值"
End If
Me.Form.Controls.Add(oLiteral)
End Sub
在上面的程式碼中,在面頁第一次執行時設定 Literal 的 Text 屬性值, 而按鈕 PostBack 後,理論上應該會由 ViewState 還原 Literal 的 Text 屬性值。可是實際執行時會發現,當 PostBack 時 Literal 的 Text 值不見了??
針對上面的問題,將程式碼做如下小修改,就是將 Literal 控制項加入頁面的動作往上移至設定 Literal 的 Text 屬性值之前。
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Dim oLiteral As New Literal()
Me.Form.Controls.Add(oLiteral)
If Not Me.IsPostBack Then
oLiteral.Text = "初始值"
End If
End Sub
重新執行程式,你會發覺竟然按鈕 PostBack 後,Literal 的 Text 屬性值會被保留了。
為什麼會發生這種情形呢?這是因為 Literal 的 Text 屬性是直接存取 ViewState 的原因,當動態新增的控制項未被加入頁面中時,控制項本身是無法存取 ViewState 時,所以動態新增的 Literal 控制項,在未加入執行 Me.Form.Controls.Add(oLiteral) 加入頁面前,設定它的 Text 屬性值,是無法被存入 ViewState 中,也就導致為什麼 PostBack 時,Literal 的 Text 屬性值不會被保留的原因了。
所以結論是,動態建立的控制項,最好馬上執行 Controls.Add 先加入頁面中,再去設定它的相關屬性值,才不會發生設定的屬性值無法寫入 ViewState 的情形。