前言:
三易其名,是因為根據網友的建議來了。所以改成了asp.net控制項開發。呵呵,不瞎扯了,上一節講到了複合控制項的基礎概念,今天就深入學習複合控制項視圖是如何跟蹤子控制項狀態的。是如何儲存子控制項狀態的呢,是如何載入子控制項狀態的呢。
本文:
帶著這些問題,進入我們的學習環節,從上面的幾節中,我知道瞭解control類中有內建用來跟蹤、儲存和恢複子控制項
的狀態。我們也知道複合控制項也是繼承於control(controlàWebControlà自訂複合控制項)而來的。在開始跟蹤視圖狀
態階段中, Control依次調用Controls 集合中控制項的TrackViewState方法,開始跟蹤子控制項的狀態。但是,如果某個子
控制項是在父控制項已經開啟跟蹤狀態後被添加到Controls 集合中的,那麼子控制項的TrackViewState方法在它被添加到控制項
樹的同時被調用。
我們在建立複合控制項時。有這樣的一個重寫方法。
Protected override void CreatedChildControls()
{
//………
This.Controls.Add(…);
//………
}
在這個重寫的方法中調用了ControlCollection中Add方法(Controls.Add)。
其虛擬碼為:
public virtural void Add(Control child)
{
………
Int index=this._size;
this._size++;
this._owner.AddedControl(control,index);//_owner是Control類,在//這裡調用了 Control內部方法AddedControl;
……..
}
說到這裡,我們有必要來看看AddedControl方法的內部實現。AddedControl(Control control, int
index)方法,將子控制項添加到容器控制項中。 在AddedControl中會對子控制項的ViewState做一些處理。
在此時,載入檢視狀態。調用了每個子控制項的TrackViewState()這個方法
AddedControl虛擬碼:
protected internal virtual void AddedControl(Control control, int index)
{ ….
control.LoadViewStateRecursive(savedState); //這裡開始跟蹤檢視狀態,添加入statebag中
}
在(savestateview)儲存檢視狀態階段時,Control先調用SaveViewState 方法。預設情況下,該方法調用
ViewState字典的SaveView。並儲存返回的對象。作為控制項檢視狀態的第一部分。Control接下來對控制項樹中的每個子控制項
調用SaveViewState .如果返回的子控制項狀態不為空白。那麼Control在兩個ArrayList中儲存該控制項的編號(在Controls
集合中)用來序列化。這些子控制項的狀態不為空白,而第二個ArrayList儲存了子控制項所儲存的狀態。最後,在該階段的最後,
Control返回它的三部分檢視狀態。
整個複合控制項樹的ViewState是怎麼儲存和讀取的呢?
在Control內部有兩個internal的方法:
internal object SaveViewStateRecursive();
internal void LoadRecursive();
這兩個方法由調用Control的SaveViewStateRecursive()方法,這個方法就是通過遞迴調用每一個
Control.Controls的SaveViewStateRecursive方法來儲存控制項樹中所有控制項的ViewState。到這裡,可能聰明的朋友
要問了,既然SaveViewStateRecursive是遞迴調用儲存的方法,那麼我們上面寫的SaveViewState()方法又有什麼用
呢?
我們知道,Control.Controls可能會有很多個,而且我們的SaveViewState()只儲存了當前控制項的資料,而沒
有記錄控制項樹的結構,那麼如果我們遞迴SaveViewState()方法來儲存資料的話,那麼控制項樹的結構就會丟失,那麼Load
的時候就沒辦法還原了,實際上在SaveViewStateRecursive方法中大致的代碼是這樣:
[1] 擷取控制項自己的ViewState(調用SaveViewState方法)
[2] 迴圈子控制項
{
定義兩個動態數組,一個儲存控制項的索引,一個儲存遞迴調用子控制項SaveViewStateRecursive方法返回的值
}
[3] 定義一個Triplet // Third中儲存的是當前頁面需要PostBack的控制項名的列表,Triplet這個類型,實際上這個類在MSDN中查一下得到,它就是一個包含了三個對象的對象,有三個屬性:First、Second、Thrid
[4] First儲存本控制項的ViewState
[5] Second儲存子控制項的索引
[6] Third儲存遞迴子控制項SaveViewStateRecursive方法的傳回值
[7] 返回Triplet
這樣就儲存了整個控制項樹的ViewState和控制項樹的結構
Load的方式與Save差不多,只是Load的時候會從savedState中擷取子控制項的索引來依次遞迴子控制項的
LoadRecursive()方法,這樣才能保證正確的把儲存的資料傳給子控制項
在(loadViewState)載入檢視狀態時,Control執行了它在儲存檢視狀態階段中執行的相返操作。頁面在該階
段傳給Control的狀態和控制項在上一次請求的最後儲存的狀態一致。Control通過調用LoadViewState方法來載入所儲存狀
態的第一部分,該方法依次把儲存的狀態載入入ViewState字典。接下來,Control訪問Controls集合,把其餘的狀態載入
子控制項,那麼其剩下的狀態將由代表子控制項編號和儲存狀態的ArrayList組成。Control用這些編號和狀態把狀態載入入子控
件,這些子控制項的狀態是在前一次請求的最後儲存的,這樣。就完成了控制項及其子控制項狀態恢複。如果在該階段還沒有建立
子控制項,那麼Control儲存子控制項的狀態,留做以後使用。接下來當子控制項被建立和添加到控制項樹時,Control把狀態載入
子控制項。注意。檢視狀態跟蹤是在載入檢視狀態階段之前開啟的。因此,通過使用檢視狀態自動回復的任何控制項屬性都標記
起來。並且在儲存檢視狀態階段中重新儲存在檢視狀態中。回傳時,這些屬性在載入檢視狀態階段重新載入,因此檢視狀態
機制在接下來的請中被持續儲存。
剛剛在每個狀態管理階段講解的步驟都是在控個把樹中遞迴執行的。因些控制項的檢視狀態代表了控制項層次的組合視
圖狀態。 Control用Controls集合中子控制項的編號來標識子控制項的已儲存的檢視狀態。Control並沒有用到子控制項的類型
或ID,這樣能達到更高的效能。因為它減少了檢視狀態的大小。但是。這意味著檢視狀態機制只有當控制項樹在加傳重建軍時
採用的次序跟在前一次請法度的最後檢視狀態儲存次序是一到的情況下才能工作。可能通過重載Controls屬性來維持
CreateChildControls中控制項建立次序。
例如:
Public override ControlCollection controls{
get{
EnsureChildControls();
Return base.Controls;
}
}
這段代碼將使在CreateChildControls中建立的子控制項在由使用者代碼添加其他控制項之前被添加控制項樹,因此。在
CreateChildControls中建立的子控制項回傳時按儲存順序被重新建立。這樣頁面框可以通過使用檢視狀態來恢複它們的狀態。
後記:
1.net組件開發系列(—)之武術系列-----------馬步功 之基本功
2.net組件開發系列(—)之武術系列--------太極拳 開發ajax控制項
3..net組件開發系列之武術系列 武術招數 控制項生命週期與控制項事件機制
4..net控制項開發系列 事件處理機制 三個介面兩個方法
5..net控制項開發(五)之 深入理解控制項的呈現原理
6..net控制項開發(六)之深究控制項樣式
7..net控制項開發(七)之複合控制項(1)概念基礎篇