在页面生命周期执行时 Page 对象在 SaveState 阶段都发生了什么事?
先看下 SaveViewState 的源码:
1 // Answer any state this control or its descendants want to save on freeze. 2 // The format for saving is Triplet(myState, ArrayList childIDs, ArrayList childStates), 3 // where myState or childStates and childIDs may be null. 4 internal object SaveViewStateRecursive() { 5 if (flags[disableViewState]) 6 return null; 7 8 object adapterState = null; 9 if (_adapter != null) { 10 adapterState = _adapter.SaveAdapterViewState(); 11 } 12 13 object controlSavedState = SaveViewState(); 14 15 ArrayList childStates = null; 16 if (HasControls()) { 17 ControlCollection occasionalFieldControls = _occasionalFields.Controls; 18 int occasionalFieldControlCount = occasionalFieldControls.Count; 19 20 bool useId = LoadViewStateByID; 21 for (int i = 0; i < occasionalFieldControlCount; i++) { 22 Control child = occasionalFieldControls[i]; 23 object childState = child.SaveViewStateRecursive(); 24 if (childState != null) { 25 if (childStates == null) { 26 childStates = new ArrayList(occasionalFieldControlCount); 27 } 28 29 if (useId) { 30 child.EnsureID(); 31 childStates.Add(child.ID); 32 } 33 else { 34 childStates.Add(i); 35 } 36 childStates.Add(childState); 37 } 38 } 39 } 40 41 if (_adapter != null) { 42 if ((controlSavedState != null) || (adapterState != null) || (childStates != null)) { 43 return new Triplet(controlSavedState, adapterState, childStates); 44 } 45 } 46 else { 47 if ((controlSavedState != null) || (childStates != null)) { 48 return new Pair(controlSavedState, childStates); 49 } 50 } 51 52 return null; 53 }
从上面的源码可以看出当页面运行至 SaveState 阶段时,将调用其自身 SaveAllState() 方法,在这个方法内部,做了两件事,第一件事就是保存控件状态,即ControlState,第二件事就是保存控件视图状态,即ViewState。ControlState我们放到以后再说,今天说说ViewState,在SaveAllState()这个方法内部,调用控件的SaveViewStateRecursive()方法,在这个方法的内部,调用控件的SaveViewState方法
页面到 SaveState 阶段时,会调用自身 SaveAllState() 方法并且在这个方法内部执行两个动作:保存控件状态 (ControlState) 和保存控件视图状态 (ViewState) 。 ControlState 等后面有时间再跟大家分享下,今天主要聊下 ViewState ,在 SaveAllState() 这个方法内部调用控件的 SaveViewStateRecursive() 方法,并且在这个方法内部再去调用 SaveViewState 方法。
Line 5:比较值得注意,平常在设置 ASP.NET 前台页面会经常去接触 EnableViewState 属性,而 flags[disableViewState] 是与 EnableViewState 相对应的。从这里是不是已经 get 到什么了呢?
if (flags[disableViewState])
最后简单写个示例,来看看页面是如何递归保存其内部控件的视图状态:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Xudaxia.ViewState.Test</title> </head> <body> <form id="form1" runat="server"> <div> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> </div> </form> </body> </html>
上面这个结构就不多说了,来看看这个页面对应的控件树: