Page对象在Init阶段递归调用其内部控件的TrackViewState()方法
我们知道,Page对象Init阶段,要调用Control.InitRecursive方法,这个方法的内部会递归调用其内部控件的TrackViewState()方法,我们先看看Control.InitRecursive方法的源码:
internal virtual void InitRecursive(Control namingContainer) {
ResolveAdapter();
if (_occasionalFields != null && _occasionalFields.Controls != null) {
if (flags[isNamingContainer]) {
namingContainer = this;
}
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
Control control = _occasionalFields.Controls[i];
// Propagate the page and namingContainer
control.UpdateNamingContainer(namingContainer);
if ((control._id == null) && (namingContainer != null) && !control.flags[idNotRequired]) {
control.GenerateAutomaticID();
}
control._page = Page;
control.InitRecursive(namingContainer);
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
// Only make the actual call if it hasn't already happened (ASURT 111303)
if (_controlState < ControlState.Initialized) {
_controlState = ControlState.ChildrenInitialized; // framework also initialized
if ((Page != null) && !DesignMode) {
if (Page.ContainsTheme && EnableTheming) {
ApplySkin(Page);
}
}
if (_adapter != null) {
_adapter.OnInit(EventArgs.Empty);
}
else {
OnInit(EventArgs.Empty);
}
_controlState = ControlState.Initialized;
}
// track all subsequent state changes
TrackViewState();
#if DEBUG
ControlInvariant();
#endif
}
Control.TrackViewState()方法源码:
ResolveAdapter();
if (_occasionalFields != null && _occasionalFields.Controls != null) {
if (flags[isNamingContainer]) {
namingContainer = this;
}
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
Control control = _occasionalFields.Controls[i];
// Propagate the page and namingContainer
control.UpdateNamingContainer(namingContainer);
if ((control._id == null) && (namingContainer != null) && !control.flags[idNotRequired]) {
control.GenerateAutomaticID();
}
control._page = Page;
control.InitRecursive(namingContainer);
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
// Only make the actual call if it hasn't already happened (ASURT 111303)
if (_controlState < ControlState.Initialized) {
_controlState = ControlState.ChildrenInitialized; // framework also initialized
if ((Page != null) && !DesignMode) {
if (Page.ContainsTheme && EnableTheming) {
ApplySkin(Page);
}
}
if (_adapter != null) {
_adapter.OnInit(EventArgs.Empty);
}
else {
OnInit(EventArgs.Empty);
}
_controlState = ControlState.Initialized;
}
// track all subsequent state changes
TrackViewState();
#if DEBUG
ControlInvariant();
#endif
}
/// <devdoc>
/// <para>Turns on tracking of view state changes to the control
/// so that they can be stored in the <see langword='StateBag'/>
/// object.</para>
/// </devdoc>
protected virtual void TrackViewState() {
if (_viewState != null)
_viewState.TrackViewState();
flags.Set(marked);
}
/// <para>Turns on tracking of view state changes to the control
/// so that they can be stored in the <see langword='StateBag'/>
/// object.</para>
/// </devdoc>
protected virtual void TrackViewState() {
if (_viewState != null)
_viewState.TrackViewState();
flags.Set(marked);
}
下边我用一个简单的示例,来表示一下这个过程:
1Code
2<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
3
4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5<html xmlns="http://www.w3.org/1999/xhtml">
6<head runat="server">
7 <title>无标题页</title>
8</head>
9<body>
10 <form id="form1" runat="server">
11 <div>
12 <asp:Literal ID="Literal1" runat="server"></asp:Literal></div>
13 </form>
14</body>
15</html>
2<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
3
4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5<html xmlns="http://www.w3.org/1999/xhtml">
6<head runat="server">
7 <title>无标题页</title>
8</head>
9<body>
10 <form id="form1" runat="server">
11 <div>
12 <asp:Literal ID="Literal1" runat="server"></asp:Literal></div>
13 </form>
14</body>
15</html>
上边是一段简单的代码,下边用顺序图的方式来说明一下这段代码的主要对象(Page,HtmlForm,Literal)是如何递归调用子控件的TrackViewState()方法: