引言
正如在前兩個任務中所看到的,我們使用視圖(ViewState)保存自定義控件 屬性,ViewState實際上是一個StateBag對象,開發人員使用鍵/值的方法向視圖 中保存或讀取設置,最終發送給用戶的HTML頁面中會包含一個隱藏域,該隱藏域 中保存了經過序列化後的值。如果過分使用視圖的話,會導致頁面急劇增大,雖 然現在網絡帶寬已經不是限制條件,但這仍然是一個不太好的設計,因此開發人 員有時會禁用視圖狀態。
對於自定義控件來說,如果禁用視圖狀態可能導致控件不能夠正常工作,讀者 可以使用第一次任務裡開發的星級控件,禁用頁面的視圖狀態(設置Page指令 EnableViewState屬性為false)並在在頁面的加載(Page_Load)事件裡輸入如下 代碼以設置分數:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) star.Score = 4; }
並在ASPX頁面上放置一個服務器端按鈕以引起回發事件,預覽該頁面並點擊按 鈕,會發生什麼情況?由於提交按鈕引起回發IsPostBack屬性為true,即不會執 行分數設置操作,並且因為禁用了視圖狀態,在頁面生命周期裡運行時無法從視 圖狀態中恢復分數,所以會導致沒有分數:
圖3-1 禁用了視圖狀態的自定義控件
分析
在.NET1.X版本裡,視圖狀態被作為一個整體,要不允許要麼禁止,對於控件 開發人員來說非常不方便,與控件相關的數據放置在ViewState裡,一旦被禁用後 ,可能就會出問題。比較幸運的是,對於這種情況,微軟及時做出了反應。在 ASP.NET2.0裡,出現了一個新的概念——控件狀態。
控件狀態實際上是一種特殊的視圖狀態,它仍然保存在客戶端的隱藏域中,但 是它並不會受視圖狀態啟用/禁用的影響,也就是說,即使將ViewState禁用,運 行時仍然能正確的恢復在控件狀態中保存的數據。
為了使用控件狀態,僅僅需要做額外的幾個工作:
1. 向頁面注冊使用控件狀態
2. 在控件狀態保存事件(Control類的SaveControlState方法)中保存相關數 據
3. 在控件狀態讀取事件(Control類的LoadControlState方法)中讀取保存的 數據
需要說明的一點是,正因為控件狀態始終都會發送到客戶端,所以將大量數據 保存到控件狀態中顯然不是一件太好的事件,始終應該只保存影響控件使用的關 鍵的核心的數據。
為了能夠使頁面視圖狀態被禁止後控件仍然能夠正常使用,將星級控件的得分 保存在控件狀態中。