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    }

在这个方法中,第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        }
 


在上边的源代码中,第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这三个对象对应的顺序图为:

 
posted @ 2008-04-15 17:06  王庆  阅读(948)  评论(0编辑  收藏  举报