Page对象在LoadState阶段都做了什么?
我们知道,页面的每次回发,都少不了LoadState阶段,在这个阶段,我们调用页面的LoadAllState()方法,下边我们看看这个方法的源码:
1
private void LoadAllState() {
2
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
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
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
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
}
private void LoadAllState() {2

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

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 states15
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 hierarchy29

30
// Is there any state?31
if (allSavedViewState != null) { 32
// Get the hash code from the state33
string hashCode = (string) allSavedViewState.First; 34
35
// If it's different from the current one, the layout has changed36
int viewhash = Int32.Parse(hashCode, NumberFormatInfo.InvariantInfo); 37
_fPageLayoutChanged = viewhash != GetTypeHashCode();38

39
// If the page control layout has changed, don't attempt to40
// 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
}在这个方法中,第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
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
25
try {
26
if ((adapterState != null) && (_adapter != null)) {
27
_adapter.LoadAdapterViewState(adapterState);
28
}
29
30
if (controlState != null) {
31
LoadViewState(controlState);
32
}
33
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
}
internal void LoadViewStateRecursive(object savedState) { 2
// nothing to do if we have no state3
if (savedState == null || flags[disableViewState]) 4
return;5

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

25
try { 26
if ((adapterState != null) && (_adapter != null)) {27
_adapter.LoadAdapterViewState(adapterState); 28
} 29

30
if (controlState != null) { 31
LoadViewState(controlState);32
}33

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
}
在上边的源代码中,第11行,将传入的object对象转换成Pair或Triplet对象,具体转换成什么对象,和Control.SaveViewStateRecursive有直接的关系,对比着SaveViewStateRecursive方法的实现,要理解LoadViewStateRecursive很容易。我们这里暂且也Pair对象为例,我们在代码的30-31行能看到,Pair.First对应当前控件的视图状态,如果这个视图状态不为null,将调用控件的LoadViewState方法。在代码的第34-41行能看到,Pair.Second是当前控件的子控件的视图信息,通过LoadChildViewStateByID方法或LoadChildViewStateByIndex方法,将试图状态传递给子控件。在这两个方法内部,又会调用子控件的LoadViewStateRecursive方法,开始新一轮的循环。我们用下边一段简单的来做一个说明:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Trace="true" EnableViewState="false" %>
<%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>无标题页</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Literal ID="Literal1" runat="server"></asp:Literal>
<asp:Button ID="Button1" runat="server" Text="Button" /></div>
</form>
</body>
</html>
这段代码在页面的LoadState阶段,Page,HtmlForm,Literal这三个对象对应的顺序图为:



浙公网安备 33010602011771号