Page对象在LoadState阶段都做了什么?
我们知道,页面的每次回发,都少不了LoadState阶段,在这个阶段,我们调用页面的LoadAllState()方法,下边我们看看这个方法的源码:
1
private void LoadAllState() {
2![](/Images/OutliningIndicators/InBlock.gif)
3
object state = LoadPageStateFromPersistenceMedium();
4
IDictionary controlStates = null;
5
Pair allSavedViewState = null;
6
Pair statePair = state as Pair;
7
if (state != null) {
8
controlStates = statePair.First as IDictionary;
9
allSavedViewState = statePair.Second as Pair;
10
}
11![](/Images/OutliningIndicators/InBlock.gif)
12
// The control state (controlStatePair) was saved as an dictionary of objects:
13
// 1. A list of controls that require postback[under the page id]
14
// 2. A dictionary of control states
15
16
if (controlStates != null) {
17
_controlsRequiringPostBack = (ArrayList)controlStates[PageRegisteredControlsThatRequirePostBackKey];
18
19
if (_registeredControlsRequiringControlState != null) {
20
foreach (Control ctl in _registeredControlsRequiringControlState) {
21
ctl.LoadControlStateInternal(controlStates[ctl.UniqueID]);
22
}
23
}
24
}
25
26
// The view state (allSavedViewState) was saved as an array of objects:
27
// 1. The hash code string
28
// 2. The state of the entire control hierarchy
29![](/Images/OutliningIndicators/InBlock.gif)
30
// Is there any state?
31
if (allSavedViewState != null) {
32
// Get the hash code from the state
33
string hashCode = (string) allSavedViewState.First;
34
35
// If it's different from the current one, the layout has changed
36
int viewhash = Int32.Parse(hashCode, NumberFormatInfo.InvariantInfo);
37
_fPageLayoutChanged = viewhash != GetTypeHashCode();
38![](/Images/OutliningIndicators/InBlock.gif)
39
// If the page control layout has changed, don't attempt to
40
// load any more state.
41
if (!_fPageLayoutChanged) {
42
// UNCOMMENT FOR DEBUG OUTPUT
43
// WalkViewState(allSavedViewState.Second, null, 0);
44
LoadViewStateRecursive(allSavedViewState.Second);
45
46
}
47
}
48
}
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
2
![](/Images/OutliningIndicators/InBlock.gif)
3
![](/Images/OutliningIndicators/InBlock.gif)
4
![](/Images/OutliningIndicators/InBlock.gif)
5
![](/Images/OutliningIndicators/InBlock.gif)
6
![](/Images/OutliningIndicators/InBlock.gif)
7
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
8
![](/Images/OutliningIndicators/InBlock.gif)
9
![](/Images/OutliningIndicators/InBlock.gif)
10
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
11
![](/Images/OutliningIndicators/InBlock.gif)
12
![](/Images/OutliningIndicators/InBlock.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/InBlock.gif)
16
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
17
![](/Images/OutliningIndicators/InBlock.gif)
18
![](/Images/OutliningIndicators/InBlock.gif)
19
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
20
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
21
![](/Images/OutliningIndicators/InBlock.gif)
22
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
23
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
24
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
25
![](/Images/OutliningIndicators/InBlock.gif)
26
![](/Images/OutliningIndicators/InBlock.gif)
27
![](/Images/OutliningIndicators/InBlock.gif)
28
![](/Images/OutliningIndicators/InBlock.gif)
29
![](/Images/OutliningIndicators/InBlock.gif)
30
![](/Images/OutliningIndicators/InBlock.gif)
31
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
32
![](/Images/OutliningIndicators/InBlock.gif)
33
![](/Images/OutliningIndicators/InBlock.gif)
34
![](/Images/OutliningIndicators/InBlock.gif)
35
![](/Images/OutliningIndicators/InBlock.gif)
36
![](/Images/OutliningIndicators/InBlock.gif)
37
![](/Images/OutliningIndicators/InBlock.gif)
38
![](/Images/OutliningIndicators/InBlock.gif)
39
![](/Images/OutliningIndicators/InBlock.gif)
40
![](/Images/OutliningIndicators/InBlock.gif)
41
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
42
![](/Images/OutliningIndicators/InBlock.gif)
43
![](/Images/OutliningIndicators/InBlock.gif)
44
![](/Images/OutliningIndicators/InBlock.gif)
45
![](/Images/OutliningIndicators/InBlock.gif)
46
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
47
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
48
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
在这个方法中,第3行,通过LoadPageStateFromPersistenceMedium()方法,得到一个Pair对象,Pair.First对应的是控件的ControState,这个我们放到以后再谈,Pair.Second对应控件的视图状态。第44行,调用控件的LoadViewStateRecursive方法,这个方法是递归载入控件视图状态的开始,下边我们列出这个方法的源代码:
1
internal void LoadViewStateRecursive(object savedState) {
2
// nothing to do if we have no state
3
if (savedState == null || flags[disableViewState])
4
return;
5![](/Images/OutliningIndicators/InBlock.gif)
6
if (Page != null && Page.IsPostBack) {
7
object controlState = null;
8
object adapterState = null;
9
ArrayList childState = null;
10
11
Pair allSavedState = savedState as Pair;
12
if (allSavedState != null) {
13
controlState = allSavedState.First;
14
childState = (ArrayList)allSavedState.Second;
15
}
16
else {
17
Debug.Assert(savedState is Triplet);
18
Triplet t = (Triplet)savedState;
19
20
controlState = t.First;
21
adapterState = t.Second;
22
childState = (ArrayList)t.Third;
23
}
24![](/Images/OutliningIndicators/InBlock.gif)
25
try {
26
if ((adapterState != null) && (_adapter != null)) {
27
_adapter.LoadAdapterViewState(adapterState);
28
}
29![](/Images/OutliningIndicators/InBlock.gif)
30
if (controlState != null) {
31
LoadViewState(controlState);
32
}
33![](/Images/OutliningIndicators/InBlock.gif)
34
if (childState != null) {
35
if (LoadViewStateByID) {
36
LoadChildViewStateByID(childState);
37
}
38
else {
39
LoadChildViewStateByIndex(childState);
40
}
41
}
42
}
43
catch (InvalidCastException) {
44
// catch all viewstate loading problems with casts. They are most likely changed control trees.
45
throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
46
}
47
catch (IndexOutOfRangeException) {
48
// catch all viewstate loading problems with indeces. They are most likely changed control trees.
49
throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
50
}
51
}
52
53
_controlState = ControlState.ViewStateLoaded;
54
}
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
2
![](/Images/OutliningIndicators/InBlock.gif)
3
![](/Images/OutliningIndicators/InBlock.gif)
4
![](/Images/OutliningIndicators/InBlock.gif)
5
![](/Images/OutliningIndicators/InBlock.gif)
6
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
7
![](/Images/OutliningIndicators/InBlock.gif)
8
![](/Images/OutliningIndicators/InBlock.gif)
9
![](/Images/OutliningIndicators/InBlock.gif)
10
![](/Images/OutliningIndicators/InBlock.gif)
11
![](/Images/OutliningIndicators/InBlock.gif)
12
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
16
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
17
![](/Images/OutliningIndicators/InBlock.gif)
18
![](/Images/OutliningIndicators/InBlock.gif)
19
![](/Images/OutliningIndicators/InBlock.gif)
20
![](/Images/OutliningIndicators/InBlock.gif)
21
![](/Images/OutliningIndicators/InBlock.gif)
22
![](/Images/OutliningIndicators/InBlock.gif)
23
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
24
![](/Images/OutliningIndicators/InBlock.gif)
25
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
26
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
27
![](/Images/OutliningIndicators/InBlock.gif)
28
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
29
![](/Images/OutliningIndicators/InBlock.gif)
30
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
31
![](/Images/OutliningIndicators/InBlock.gif)
32
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
33
![](/Images/OutliningIndicators/InBlock.gif)
34
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
35
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
36
![](/Images/OutliningIndicators/InBlock.gif)
37
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
38
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
39
![](/Images/OutliningIndicators/InBlock.gif)
40
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
41
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
42
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
43
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
44
![](/Images/OutliningIndicators/InBlock.gif)
45
![](/Images/OutliningIndicators/InBlock.gif)
46
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
47
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
48
![](/Images/OutliningIndicators/InBlock.gif)
49
![](/Images/OutliningIndicators/InBlock.gif)
50
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
51
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
52
![](/Images/OutliningIndicators/InBlock.gif)
53
![](/Images/OutliningIndicators/InBlock.gif)
54
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
在上边的源代码中,第11行,将传入的object对象转换成Pair或Triplet对象,具体转换成什么对象,和Control.SaveViewStateRecursive有直接的关系,对比着SaveViewStateRecursive方法的实现,要理解LoadViewStateRecursive很容易。我们这里暂且也Pair对象为例,我们在代码的30-31行能看到,Pair.First对应当前控件的视图状态,如果这个视图状态不为null,将调用控件的LoadViewState方法。在代码的第34-41行能看到,Pair.Second是当前控件的子控件的视图信息,通过LoadChildViewStateByID方法或LoadChildViewStateByIndex方法,将试图状态传递给子控件。在这两个方法内部,又会调用子控件的LoadViewStateRecursive方法,开始新一轮的循环。我们用下边一段简单的来做一个说明:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
这段代码在页面的LoadState阶段,Page,HtmlForm,Literal这三个对象对应的顺序图为: