1 使用者控制項的屬性持久化問題:(參考:道不遠人---深入解析ASP.NET2.0控制項開發)
問題描述:在為使用者控制項屬性賦值後,重新刷一次頁面或回傳一次伺服器,使用者控制項的屬性就會消失,但是.NET內建的控制項不會出現這種問題。
原因:要解釋上面的問題,我們需要回顧一下 HTTP協議的工作模式,HTTP是一種無狀態的斷開式串連模式,也就是說,用戶端向伺服器發出請求,伺服器端做出響應後就不在維持此次請求用戶端的資訊。在預設情況下,多次請求來自於同一個用戶端還是多個不同的用戶端,對於服務端來說處理方式沒什麼不同。
所以我們單擊頁面上的按鈕,把頁面回傳到伺服器後,伺服器並不能把頁面中的控制項的所有狀態還原到上一次請求時設定的值,因為它根本不知道上一次請求是哪一次,也沒有為每一次請求儲存曆史資訊。
解決方案:
HTTP的這種無狀態特徵為我們的開發帶來了和Winforms開發模型極不一致,使用者和控制項互動的結果不能儲存下來等問題。
而在實際開發過程中,我們又發現ASP 。NET提供的控制項卻可以很好的在頁面回傳過程中儲存自己的狀態。比如,我們在頁面中添加一個Label控制項,並在按鈕事件中添加:
this.lblHappy.text += this.lblHappy.text + "again"
Label顯示的文本可以正確地基於前次請求設定的值再加上“again”,這是怎麼回事呢?
原來ASP.NET為瞭解決儲存控制項狀態的矛盾,引入了一種叫視圖(ViewState)的特性。需要在頁面回傳過程中儲存值的控制項屬性,可以把值儲存在檢視狀態中。(1)ASP.NET架構會在呈現頁面前(伺服器把頁面發送到用戶端),把檢視狀態資訊序列化成一個字串,並儲存到頁面中一個叫"_VIEWSTATE"的隱藏表單域(<input type = 'hidden'>)中.這樣,控制項的狀態就儲存到了用戶端。(2)表單域下次回傳時(用戶端把頁面提交到伺服器),伺服器端再對提交回的_VIEWSTATE隱藏欄位的值進行還原序列化,還原各個控制項的狀態。
或者這樣解釋ViewState的原理:當請求某個頁面時,ASP.NET把所有控制項的狀態序列化成一個字串,然後做為表單的隱藏屬性送到用戶端。當用戶端把頁面回傳時,ASP.NET分析回傳的表單內容,並賦給控制項對應的值。當然這些全部是由ASP.NET負責的。
舉例說明:
Code
1 public class AlbumnUsingViewState:Albumn
2 {
3 public override string ImgUrl
4 {
5 get
6 {
7 object o = ViewSate["ImgUrl"];
8 if(o != null)
9 {
10 return (string)o;
11 }
12 return string.Empty;
13
14 }
15 set
16 {
17 ViewSate["ImgUrl"] = value;
18 }
19 }
20 }
2 動態引用使用者控制項:
直接在頁面上用拖拽的方式引用空間是非常簡單的,如果想在代碼中動態產生可以用如下方法:
(控制項的類) 名稱=(控制項的類)this.LoadControl("......ascx") 只需要控制項的類名和路徑就可以定義一個控制項。 樣本如下:Code
1 Business_UserControl_userCheckInfo UserCheckInfo1 = (Business_UserControl_userCheckInfo)LoadControl(@"UserControl\\userCheckInfo.ascx");
2 UserCheckInfo1.uidAndType = "數字";
3 Panel1.Controls.Add(UserCheckInfo3);第一行是動態產生一個控制項,第二行是為控制項的屬性賦值,第三行是把控制項放到一個容器中,顯示控制項。
結論:動態載入控制項太麻煩了,涉及很多內部原理,不如直接把使用者控制項扔到GridView的模板裡,然後給屬性賦值來初始化。
這樣就讓.Net來儲存使用者控制項的資訊,不用我們自己操心了。