`
java-mans
  • 浏览: 11454466 次
文章分类
社区版块
存档分类
最新评论

viewstate的作用

 
阅读更多

1ViewState机制是什么?

ViewState机制是asp.net中对同一个Page的多次请求(PostBack)之间维持Page及控件状态的一种机制。在WebForm中每次请求完,Page对象都会被释放,对同一个Page的多次请求之间的状态信息,如何进行维护呢?WebForm中,每次请求都会存在客户端和服务器之间的一个交互。如果请求完成之后将一些信息传回到客户端,下次请求的时候客户端再将这些状态信息提交给服务器,服务器端对这些信息使用和处理,再将这些信息传回给客户端。这样是不是就可以对同一个Page的多次请求(PostBack)之间维持状态了。对这就是ViewState的基本工作模式。ViewState的设计目的主要就是为了将必要的信息持久化在页面中。这样通过ViewState在页面回传的过程中保存状态值,使原本没有“记忆”的Http协议变得有“记忆”起来。

2ViewState机制如何工作?

下面我们看看ViewState机制是如何具体的工作的。

2.1客户端:

我们先从客户端看起,在客户端的HTML源代码中我们可以看到下面的代码

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"

value="/wEPDwULLTE0MTAzNDUwNThkZKr77J2uy7fatyBou8PocG80X4Jt" />

这个就是ViewState在客户端的保存形式,它保存在一个ID为__VIEWSTATE的Hidden中,它的Value是使用Base64编码后的字符串。这个字符串实际上是一个对象(Pair类型)序列化之后的结果。这个对象保存了整个页面的控件树的ViewState。可以使用一些工具将这个字符串进行解码查看其内容,比如ViewStateDecoder,ViewStateAnalyzer。

2.2服务器端:

在服务器端和ViewState机制密切相关的有三个类Page,Control,StateBag。他们3者的关系如下图所示:


图1

Page继承自Control,Control和StateBag是聚合关系,在Control中有一个StateBag的实例ViewState。这三个类互相协作完成ViewState机制的大概过程如下。Page对客户端请求进行处理,在处理的过程中先是将客户端提交的_VIEWSTATE反序列化为对象,调用Control的相关方法给所有的控件装载数据,这些数据是上次请求结束后控件的状态数据。在之后的一些事件中这些状态数据可能被修改。在请求结束之前调用Control的相关方法得到所有控件的被修改过的状态数据,之后Page将其进行序列化,并返回给客户端。在Control中又具体调用StateBag类的方法完成状态数据的加载和保存。

2.2.1Page中的处理


图2 Page生命周期

1)InitRecursive

在Page的生命周期中有3处与ViewState相关,在初始化阶段调用Control. InitRecursive,它递归对所有的控件进行初始化,其中调用了Control.TrackViewState。TrackViewState中打开跟踪ViewState开关。

2)LoadAllState

在初始化完成之后会调用Page.LoadAllState,LoadAllState只有在PostBack的时候才会执行,它的主要功能是将从页面传递来的__VIEWSTATE的值反序列化为Pair类型的对象,然后将这个对象中存储的ViewState的值加载到Page及所有控件中。实际上LoadAllState加载了ControlState(控件状态)及ViewState(视图状态),本文主要是讨论ViewState,对ControlState部分的处理不进行描述。

LoadAllState中主要有两步:Page.LoadPageStateFromPersistenceMedium和Control.LoadViewStateRecursive。

在LoadPageStateFromPersistenceMedium中发生了如下的调用层次

Page.LoadPageStateFromPersistenceMedium

èHiddenFieldPageStatePersister.Load

èObjectStateFormatter.Deserialize

以上完成的功能是将客户端提交的_VIEWSTATE反序列化为一个类型为Pair的对象pair。

Control.LoadViewStateRecursive中将递归加载控件的ViewState,具体在下面进行讲解。

3)SaveAllState

SaveAllState它的操作和LoadAllState相反。SaveAllState中主要有两步Control.SaveViewStateRecursive及Page SavePageStateToPersistenceMedium。

Control.SaveViewStateRecursive中将所有控件的ViewState属性递归加载到一个Pair对象中,具体实现细节在下面讲解。

Page SavePageStateToPersistenceMedium中发生如下的调用关系。

Page SavePageStateToPersistenceMedium

èHiddenFieldPageStatePersister.Save

èObjectStateFormatter.Serialize

将Control.SaveViewStateRecursive生成的对象序列化为一个字符串,并赋值给Page.ClientState属性。

在Render阶段发生如下的调用关系:

HtmlForm.RenderChildren

èPage.BeginFormRender

èPage.RenderViewStateFields

最终将ClientState属性中的值写入到HTML页面的_VIEWSTATE中。

在Control.InitRecursive中打开跟踪开关,打算对ViewState的值进行跟踪,在Page.LoadAllState中将客户端提交的__VIEWSTATE的值装载到各个控件的ViewState中,在Page.SaveAllState中将发生变化的ViewState序列化为一个字符串,在Render阶段发送回客户端。

4)ViewState序列化与反序列化

PageStatePersister是一个抽象类,是表示将ViewState信息序列化及反序列化机制的基类。在Page.LoadPageStateFromPersistenceMedium中示意代码如下:

protected internalvirtualobjectLoadPageStateFromPersistenceMedium()

{

PageStatePersisterpageStatePersister =this.PageStatePersister;

pageStatePersister.Load();

returnnewPair(pageStatePersister.ControlState, pageStatePersister.ViewState);

}

在Page.SavePageStateToPersistenceMedium中的示意代码如下:

protected internalvirtualvoidSavePageStateToPersistenceMedium(objectstate)

{

PageStatePersisterpageStatePersister =this.PageStatePersister;

Pairpair = (Pair) state;

pageStatePersister.ControlState= pair.First;

pageStatePersister.ViewState= pair.Second;

pageStatePersister.Save();

}

在Asp.net2.0中实现PageStatePersister这个抽象类,具体提供持久化机制的类是HiddenFieldPageStatePersister。它实现了Load和Save两个方法,Load时将__VIEWSTATE反序列化为一个Pair对象,Save时将Pair对象序列化为一个字符串赋值给Page.ClientState。HiddenFieldPageStatePersister中采用的格式器是ObjectStateFormatter,其实现string Serialize(object state),和object Deserialize(string serializedState)这两个方法,从而实现对Pair对象的序列化和反序列化。

public string Serialize(object state)中的示意代码如下:

MemoryStreammemoryStream =GetMemoryStream();

Serialize(memoryStream, state);

byte[] buf = memoryStream.GetBuffer();

if(RequiresViewStateEncryptionInternal)

{

buf =MachineKeySection.EncryptOrDecryptData(true, buf,this.GetMacKeyModifier(),0, length);

length = buf.Length;

}

elseif(EnableViewStateMac)

{

buf =MachineKeySection.GetEncodedData(buf,this.GetMacKeyModifier(),0,reflength);

}

returnConvert.ToBase64String(buf,0, length);

将state序列化为内存流,在将其转换为字节流。如果需要加密则对其进行加密处理,否则需要Mac则进行Mac处理。最后将字节流进行Base64编码转换为字符串。

public object Deserialize(string serializedState)中的示意代码如下:

byte[] buf =Convert.FromBase64String(serializedState);

intlength = buf.Length;

if(ContainsEncryptedViewState)

{

buf =MachineKeySection.EncryptOrDecryptData(false, buf,this.GetMacKeyModifier(),0, length);

length = buf.Length;

}

elseif(EnableViewStateMac)

{

buf =MachineKeySection.GetDecodedData(buf,this.GetMacKeyModifier(),0, length,reflength);

}

MemoryStreammemoryStream =GetMemoryStream();

memoryStream.Write(buf,0, length);

returnthis.Deserialize(memoryStream);

将字符串进行Base64解码为字节流,如果需要解密则进行解密处理,否则需要进行需要Mac则进行Mac处理,将字节流转换为内存流,进行反序列化返回Pair对象。


顺便交流一下我的小经验:

1、尽量不要用asp.net自带的验证控件,在批量录入数据时大量的验证控件生成很多页面代码;
2、如果htmlcontrol能满足你的要求,就可以不用webcontrol;
3、很多时候用repeater也很不错,不一定都用gridview;
4、对于ViewState 比较大的页面,可以考虑压缩;
5、对于移动的应用,可以考虑把ViewState 放到session中;
6、用javascript动态创建控件,也能够压缩不少页面代码;
7、利用一些成熟的框架(如jquery),能够大大提高开发效率,提高UI体验,还得靠javascript做很多工作;

8、如果控件的ViewState没有必要,就要设置EnableViewState =false,对于gridview,ViewState有蛮多重要的信息(如分页信息),所以不能gridview.EnableViewState =false,但是可以用gridview.Controls[0].EnableViewState=false,以清除没有用的ViewState。




ViewState用于记录同一个Page的不同请求之间保存和还原服务器控件的视图状态。那么它到底能存储什么信息呢?主要有两部分组成:

1 程序员通过调用ViewState[""]存储的信息
2 通过编程改变的控件状态

ViewState的使用

Asp.net内置控件的状态值都是通过ViewState存储的,如Textbox的Text属性值、TextMode属性等

[Bindable(true,BindingDirection.TwoWay),PersistenceMode(PersistenceMode.EncodedInnerDefaultProperty),Editor("System.ComponentModel.Design.MultilineStringEditor,System.Design,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a",typeof(UITypeEditor)),Localizable(true),WebCategory("Appearance"),DefaultValue(""),WebSysDescription("TextBox_Text")]
publicvirtualstringText
{
get
{
stringstr=(string)this.ViewState["Text"];
if(str!=null)
{
returnstr;
}

returnstring.Empty;
}

set
{
this.ViewState["Text"]=value;
}

}


[Themeable(
false),WebSysDescription("TextBox_TextMode"),DefaultValue(0),WebCategory("Behavior")]
publicvirtualTextBoxModeTextMode
{
get
{
objectobj2=this.ViewState["Mode"];
if(obj2!=null)
{
return(TextBoxMode)obj2;
}

returnTextBoxMode.SingleLine;
}

set
{
if((value<TextBoxMode.SingleLine)||(value>TextBoxMode.Password))
{
thrownewArgumentOutOfRangeException("value");
}

this.ViewState["Mode"]=value;
}

}

也可以使用ViewState存储自己想要存储的信息,如ViewState["no"] =this.no

注:ViewState记录的信息只用于同一个页面的请求间使用,不同页面之间不起作用

ViewState作用时间

在Page的生命周期中,并不是任何时候都可以访问ViewState。必须在InitComplete事件开始才能访问,在PreInit及Init事件内不起作用。可以显示的调用TraceViewState()函数来启动ViewState。

protectedoverridevoidOnInit(EventArgse)
(
boolret;
ret
=ViewState.IsItemDirty("item");//returnsfalse
ViewSTate[
"item"]="1";
ret
=ViewState.IsItemDirty("item");//returnsfalse

base.OnInit(e);
}

在Init方法里,即使给ViewState赋值,也无法使用。

protectedvoidPage_InitComplete(objectsender,EventArgse)
{
boolret;
ret
=ViewState.IsItemDirty("item");//returnsfalse
ViewState[
"item"]="1";
ret
=ViewState.IsItemDirty("item");//returnstrue
}

在InitComplete事件里,由于调用了TrackViewState(),在ViewState内保存的项就会被保存(项被标记为Dirty)

ViewState 和 PostBack

控件的ViewState功能可以开启也可以关闭,如果关闭,是否在post过程中就不会保存任何信息呢。下面是test code

<scriptrunat="server">
voidbtnSubmit_Click(Objectsender,EventArgse)
{
lblMessage.Text
="Goodbyeeveryone";
lblMessage1.Text
="Goodbyeeveryone";
txtMessage.Text
="Goodbyeeveryone";
txtMessage1.Text
="Goodbyeeveryone";
}

</script>
<formid="form1"runat="server">

<asp:Labelrunat="server"ID="lblMessage"EnableViewState=true
Text
="HelloWorld"></asp:Label>
<asp:Labelrunat="server"ID="lblMessage1"EnableViewState=false
Text
="HelloWorld"></asp:Label>
<asp:Textboxrunat="server"ID="txtMessage"EnableViewState=true
Text
="HelloWorld"></asp:Textbox>
<asp:Textboxrunat="server"ID="txtMessage1"EnableViewState=false
Text
="HelloWorld"></asp:Textbox>

<br/>
<asp:Buttonrunat="server"Text="ChangeMessage"ID="btnSubmit"></asp:Button>
<br/>
<asp:ButtonID="btnEmptyPostBack"runat="server"Text="EmptyPostback"></asp:Button>
</form>

由两个Label、两个Textbox、两个Button组成。点击“Change Message”,执行btnSubmit_click事件,将所有控件的值被置为“Goodbye everyone”,这与预期结果一样。然后,点击“Empty PostBack”引发空回送,EnableViewState=false的控件(一个Label、一个Textbox)是否不保存前一个状态(Goodbye everyone)呢。结果是Label的值恢复为Hello World,而Textbox的值保留了前一个值“Goodbye everyone”。

其原因是在于asp.net 2.0新增的事件LoadPostbackData,在此事件中,实现了IPostBackEventHandler的控件会使用回送数据重置控件的状态。有以下三个重要点:
1 此阶段的数据不使用ViewState中获取的,而是从回送数据表中获取的
2只把回送数据分发给实现了IPostBackEventHandler的控件,如Textbox、Checkbox
3 由于此事件发生在LoadViewState事件之后,此时会重写控件来自ViewState的值

TextBox的LoadPostBackData()方法定义如下:

protectedvirtualboolLoadPostData(stringpostDataKey,NameValueCollectionpostCollection)
{
base.ValidateEvent(postDataKey);
stringtext=this.Text;
stringstr2=postCollection[postDataKey];
if(!this.ReadOnly&&!text.Equals(str2,StringComparison.Ordinal))
{
this.Text=str2;
returntrue;
}

return
false;
}

其中postDataKey为控件的主要标识符,postCollection为发送到服务器的名/值对的集合。首先进行验证操作,然后根据控件的标识从键值对集合中取出回送数据,如果允许更改,则更改Text属性值,这样从用户传回来的值就被重新设置到Textbox控件上,用户看到的还是提交前的数据。

子控件的ViewState

每个控件一般会经历如下几个阶段:

1。Instantiate
2。Initialize
3。Begin Tracking View State
4。Load View State (postback only)
5。Load Postback Data (postback only)
6。Load
7。Raise Changed Events (postback only, optional)
8。Raise Postback Events (postback only, optional)
9。PreRender
10。SaveViewState
11。Render
12。Unload
13。Dispose

对于Page对象,是在InitComplete()事件中开启ViewState的,而Page内的control则是在Init后开启的。test code如下;

<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>UntitledPage</title>
</head>
<body>
<formid="form1"runat="server">
<div>
<asp:LabelID="Label1"runat="server"Text="StaticText"></asp:Label>
<asp:ButtonID="Button1"runat="server"Text="PostBack"
onclick
="Button1_Click"/>
</div>
</form>
</body>
</html>

/********************************************************************/

protectedvoidPage_PreInit(objectsender,EventArgse)
{
if(!IsPostBack)
{
Label1.Text
="dymaticText";
}

}


protectedvoidPage_Init(objectsender,EventArgse)
{
if(!IsPostBack)
{
Label1.Text
="dymaticText";
}

}


protectedvoidPage_Load(objectsender,EventArgse)
{
if(!IsPostBack)
{
Label1.Text
="dymaticText";
}

}


protectedvoidButton1_Click(objectsender,EventArgse)
{

}

在PreInit、Init、及Load事件中,修改Label1的Text属性值。下面将测试这三个事件,哪些会使ViewState保存通过program修改的控件值。

注释掉PreInt、Init中代码,保留Load事件,由于在Load事件在InitComplete事件之后,所以毫无疑问,ViewState会保存对Label1控件的修改,将"symaticText"值保存在"__VIEWSTATE"隐藏字段中,当按下Button按钮回送页面时,在LoadViewState阶段,会从ViewState中提取dymaticText,并将值赋值给Label1控件的Text属性。最终显示在页面的是"dymaticText"字符串。

注释掉Init、Load,保留PreInit事件,由于PreInit事件在InitComplete事件之后,所以在此阶段更改的数据不会保存,回送后最终显示在页面的是设计时赋的值"StaticText".

注释掉PreInit、Load,保留Init事件。Init事件在InitComplete事件之前,但是回送后显示在页面的也是“dymaticText”。其原因如下:
Page Life Cycle 之一: Overview一节知道,InitComplete不是递归事件,它只能有Page对象启动,Control控件不包含此事件。Control是在Init事件中开始track ViewState的,而Page的Init是递归事件,在此阶段page对象会调用子控件的Init事件处理函数, 所以从Page.Init开始,就可以保存Page的子控件的视图状态了。这就解释了测试代码的结果。

动态子控件 和 ViewState

可以在运行时根据需要动态的加载控件到Page对象,如下面代码那样:

Labellbl=newLabel();
Page.Controls.Add(lbl);

因为动态控件是在运行时加的,它不包含在编译好的类中,所以控件树不包含动态控件。必须在Page的每一次加载过程中运行上面的代码,以示它能插入到控件树中,并最终显示到页面。对动态控件的初始化操作或添加操作都不能包含在!IsPostBack条件语句中。

此外,动态控件一旦被添加到控件组,就会执行生命周期的“追赶”过程。也就是说,它会把它错过的事件依次执行一遍。比如,如果add操作是在Page_Load事件中,当添加到Controls中后,它会依次执行Init、LoadVewState、LoadPostBackData,直至追赶到Page目前执行的Load事件。原则上,用户可以在Render之前的任意阶段添加动态控件,但一般推荐在PreInit、Init阶段,因为最好在启用ViewState的InitComplete之前把控件添加到控件树上,以保存其视图状态。

<html>
<scriptlanguage="C#"runat="server">
voidPage_Load(Objectsender,EventArgse)
{
DropDownListddlDynamic
=newDropDownList();
ddlDynamic.ID
="ddlDynamic";

form1.Controls.Add(ddlDynamic);
//(1)

if(!IsPostBack)
{
for(inti=1;i<=3;i++)
ddlDynamic.Items.Add(
newListItem(i.ToString(),i.ToString()));
}


//form1.Controls.Add(ddlDynamic);//(2)

if(IsPostBack)
{
Response.Write(
"[Page_Load]静态:"+ddlStatic.SelectedIndex+"<BR>");
Response.Write(
"[Page_Load]动态:"+ddlDynamic.SelectedIndex+"<BR>");
}

}

voidButton_Click(Objectsender,EventArgse)
{
DropDownListddlDynamic
=(DropDownList)form1.FindControl("ddlDynamic");
Response.Write(
"[Button_Click]静态:"+ddlStatic.SelectedIndex+"<BR>");
Response.Write(
"[Button_Click]动态:"+ddlDynamic.SelectedIndex+"<BR>");
}

</script>
<body>
<formid="form1"runat="server">
<asp:Buttonid="btn"runat="server"Text="ClickMe"OnClick="Button_Click"/>
<br/>
静态:
<asp:DropDownListid="ddlStatic"runat="server">
<asp:ListItemText="1"Value="1"/>
<asp:ListItemText="2"Value="2"/>
<asp:ListItemText="3"Value="3"/>
</asp:DropDownList>
<br/>
动态:
</form>
</body>
</html>

上面的测试代码中,form1.Controls.Add操作放在(1)、(2)两个不同的地方,执行结果却大不一样。

代码(1):执行结果与预期相同。首次执行时,动态下拉框填充了数据,分别选择第二项和第三项,然后点击按钮回送,页面上显示:

[Page_Load]静态:1
[Page_Load]动态:
0
[Button_Click]静态:
1
[Button_Click]动态:
2

并且两个下拉框中保存了上次选择的项。

代码(2):首次执行时,动态下拉框填充数据。分别选择第二项和第三项,然后点击按钮回送,页面显示:

[Page_Load]静态:1
[Page_Load]动态:
-1
[Button_Click]静态:
1
[Button_Click]动态:
-1

没有保存动态下拉框的选项,并且动态下拉框中没有数据。

根据前面的原理我们可以分析出,其原因如下:
1 填充下拉框的代码包含在 !IsPostBack代码内,回送时自然不会填充控件;
2 执行fomr1.Controls.Add(ddlDynamic)代码时,DropDownList实例对象会依次执行Init、LoadViewState、LoadPostbackData。把这句话放在填充数据的前面,对control所作的更改才能保存在ViewState中。而如果放在后面,只是把控件放入控件树,并没有保存对它的更改记录,在回送时,ViewState中没有它的记录。如果把 !IsPostBack去掉,就能够填充控件了。
3 去掉 !IsPostBack,虽然可以填充数据,但执行结果如下:

[Page_Load]静态:1
[Page_Load]动态:
0
[Button_Click]静态:
1
[Button_Click]动态:
2

在PageLoad阶段没能设置PostBack值,但在Button_Click阶段却正确设置了。其原因是什么呢?

Page.ProcessRequestMain函数定义如下(经删减后的部分),从它的定义中我们可以看到一个页面所经历的全过程。

privatevoidProcessRequestMain(boolincludeStagesBeforeAsyncPoint,boolincludeStagesAfterAsyncPoint)
{
HttpContextcontext
=this.Context;

if(this.PageAdapter!=null)
{
this._requestValueCollection=this.PageAdapter.DeterminePostBackMode();
}

else
{
this._requestValueCollection=this.DeterminePostBackMode();
}


this.PerformPreInit();
this.InitRecursive(null);
this.OnInitComplete(EventArgs.Empty);
this.LoadAllState();
this.ProcessPostData(this._requestValueCollection,true);
this.OnPreLoad(EventArgs.Empty);
this.LoadRecursive();
this.ProcessPostData(this._leftoverPostData,false);
this.RaiseChangedEvents();
this.RaisePostBackEvent(this._requestValueCollection);
this.OnLoadComplete(EventArgs.Empty);
this.PreRenderRecursiveInternal();
this.PerformPreRenderComplete();
this.SaveAllState();
this.OnSaveStateComplete(EventArgs.Empty);
this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));
}

从定义看出,Page在Load和LoadComplete之间还包含三个阶段:
ProcessPostData second try:在Load之后,处理未处理过的PostBack data。这种方式允许用户在Load方法内加载动态控件,并获取用户的输入数据。
RaiseChangedEvents:服务器控件通知asp.net状态发生了更改
RaisePostBackEvents:进行了加载并发出了更改通知后,在预呈现发生前触发此事件。通知引起回发的服务器控件,使其处理传入的回发事件。如Button控件的Click事件,从而进入Click事件处理程序

根据上面的分析,可以知道最后一个问题的原因了:在Load前的ProcessPostBackData阶段,由于还未对动态DropDownList填充数据,无法给它赋予post data(这里是SelectedIndex),所以在Load里无法获取用户所选的项。但在Load之后,数据已填充完成后,就可以在第二个ProcessPostBackData中设置post data了,Button_Click是在第二次ProcessPostBackData之后的RaisePostBackEvent中触发的,所以在Click事件里就能够正确获取用户所选项了

接下来仔细查看两个方法的定义:

internalvoidRaiseChangedEvents()
{
if(this._changedPostDataConsumers!=null)
{
for(inti=0;i<this._changedPostDataConsumers.Count;i++)
{
Controlcontrol
=(Control)this._changedPostDataConsumers[i];
if(control!=null)
{
IPostBackDataHandlerpostBackDataHandler
=control.PostBackDataHandler;
if(((control==null)||control.IsDescendentOf(this))&&((control!=null)&&(control.PostBackDataHandler!=null)))
{
postBackDataHandler.RaisePostDataChangedEvent();
}

}

}

}

}


privatevoidRaisePostBackEvent(NameValueCollectionpostData)
{
if(this._registeredControlThatRequireRaiseEvent!=null)
{
this.RaisePostBackEvent(this._registeredControlThatRequireRaiseEvent,null);
}

else
{
stringstr=postData["__EVENTTARGET"];
boolflag=!string.IsNullOrEmpty(str);
if(flag||(this.AutoPostBackControl!=null))
{
Controlcontrol
=null;
if(flag)
{
control
=this.FindControl(str);
}

if((control!=null)&&(control.PostBackEventHandler!=null))
{
stringeventArgument=postData["__EVENTARGUMENT"];
this.RaisePostBackEvent(control.PostBackEventHandler,eventArgument);
}

}

else
{
this.Validate();
}

}

}


[EditorBrowsable(EditorBrowsableState.Advanced)]
protectedvirtualvoidRaisePostBackEvent(IPostBackEventHandlersourceControl,stringeventArgument)
{
sourceControl.RaisePostBackEvent(eventArgument);
}

RaiseChangeedEvent事件中每一个状态发生了更改的控件(实现了IPostBackDataHandler接口)都执行RaisePostBackChangedEvent,通知asp.net该控件状态执行了更改。在此例中是DropDownList空间内容发生更改,DropDownList控件的实现内容如下:

protectedvirtualvoidRaisePostDataChangedEvent()
{
if(this.AutoPostBack&&!this.Page.IsPostBackEventControlRegistered)
{
this.Page.AutoPostBackControl=this;
if(this.CausesValidation)
{
this.Page.Validate(this.ValidationGroup);
}

}

this.OnSelectedIndexChanged(EventArgs.Empty);
}

该事件的调用引发DropDownList控件的SelectdIndecChanged事件,如果用户定义了该事件的处理程序,则进入处理程序继续执行。

RaisePostBackEvent则是调用引起回送的控件(实现了IPostBackEventHandler接口)的RaisePostBackEvent事件,从而进入回送事件处理程序。Button控件的RaisePostBackEvent实现如下:

protectedvirtualvoidRaisePostBackEvent(stringeventArgument)
{
base.ValidateEvent(this.UniqueID,eventArgument);
if(this.CausesValidation)
{
this.Page.Validate(this.ValidationGroup);
}

this.OnClick(EventArgs.Empty);
this.OnCommand(newCommandEventArgs(this.CommandName,this.CommandArgument));
}

通过触发RaisePostBackEvent进入Button的Click事件处理程序。

参考:
http://www.codeproject.com/KB/aspnet/ASPViewStateandPostBack.aspx
http://www.codeproject.com/KB/aspnet/aspnetviewstatepagecycle.aspx
http://blog.joycode.com/saucer/archive/2004/10.aspx


分享到:
评论

相关推荐

    viewstate详解

    viewstate详解,详细阐述了viewstate的用法及其作用。

    状态保存机制之ViewState概述及应用

    无状态的根本原因是:浏览器和服务器使用Socket通信,服务器将请求结果返回给浏览器后,会关闭当前Socket连接。而且服务器会在处理页面完毕后销毁页面对象。 ... 一个浏览者发出的请求都是由实现了IHttpHandler接口的...

    Cookie,Session,Application的区别与应用

    在ASP.NET中,有很多种保存信息的内置对象,如:Application,Session,Cookie,ViewState和Cache等。下面分别介绍它们的用法和区别。 方法 信息量大小 作用域和保存时间 应用范围 保存位置

    C#面试要点

    Request、Response、Sever、appliation、session、Cookies、 viewstate 4.Global文件(Global.asax)在项目中起是什么作用? 5.了解WebService吗?什么是Web Service(SOAP、UDDI、WSDL)? 6.WebService有哪些关键技术...

    不可或缺的ASP.NET内置对象

    事件四、ViewState对象保存数据取出数据总结ViewState的本质五、Session对象1.Session的原理2.属性3.方法4.用途六、Cookie对象1.Cookie的特点2.Cookie的创建3.属性4.方法5.Cookies工作原理图七、Application对象1....

    BoardGameList-CleanArchi:示例代码探索SwiftUI和使用Clean Architecture结合

    查看触发器(带有用户输入或副作用) Interactor Interactor使用Workers ,存储库和更新ViewState ViewState更新(通过绑定) View原料药该项目使用开放的API 场景我们的应用程序包含2个场景。游戏清单第一个场景是...

    精通ASP.NET.4.0网络编程 part-2

    第1篇ASP.NET网络开发关键技术第1章ASP.NET网络开发基础(教学视频87分钟)1.1...作用1.2.2创建和使用母版页1.2.3将现有页面转换为母版页或内容页1.2.4嵌套母版页1.2.5从内容页访问母版页控件1.3主题1.3.1创建和使用主题...

    精通ASP.NET.4.0网络编程 part-1

    第1篇ASP.NET网络开发关键技术第1章ASP.NET网络开发基础(教学视频87分钟)1.1...作用1.2.2创建和使用母版页1.2.3将现有页面转换为母版页或内容页1.2.4嵌套母版页1.2.5从内容页访问母版页控件1.3主题1.3.1创建和使用主题...

    JavaServer Faces 2.0, The Complete Reference

    为了适应Ajax,在JSF 2.0中引入了一个全新的ManageBean的作用范围View Scope,此作用范围是在此视图存在时有用,当导航到新的视图时失效。正暗合了ajax当前页面局部更新的道理。 还有一些特性的加强和性能方面的...

    基于Extjs的开源控件库ExtAspNet v3.1.9.rar

    ExtAspNet 是为了创建没有 JavaScript,没有 CSS,没有 UpdatePanel,没有 ViewState,没有 WebServices 的网站应用程序。  支持的浏览器: IE 7.0 、Firefox 3.6 、Chrome 3.0 、Opera 10.5 、Safari 3.0 授权...

    ASP.NET教学讲义,完整章节

    5.11 使用Viewstate保持窗体状态 99 5.12 把视图状态用作数据存储 100 5.13 利用查询字符串传递数据 101 5.14 利用隐藏的窗体字段传递数据 101 5.14 变量的作用域 102 第六章:站点设计 103 6.1 ASP.NET应用程序...

    史上最好传智播客就业班.net培训教程60G 不下会后悔

    而是通过ashx的模式开发原始的动态网站,让学员明白“请求—处理—响应模型”、“Http协议、Http无状态”、“c#代码渲染生成浏览器端JavaScript”、“ViewState的作用”、“Session的原理”等这些基本而又重要的原理...

    庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术

    6.4.1 在禁用视图状态的情况下仍然使用viewstate对象 221 6.4.2 istatemanager接口仍然可以在控件状态中使用 223 6.4.3 视图状态和控件状态组合使用规则 225 6.5 加密页面状态 225 6.6 清除页面状态 226 6.7 对...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part1

    6.4.1 在禁用视图状态的情况下仍然使用viewstate对象 221 6.4.2 istatemanager接口仍然可以在控件状态中使用 223 6.4.3 视图状态和控件状态组合使用规则 225 6.5 加密页面状态 225 6.6 清除页面状态 226 6.7 对...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part2

    6.4.1 在禁用视图状态的情况下仍然使用viewstate对象 221 6.4.2 istatemanager接口仍然可以在控件状态中使用 223 6.4.3 视图状态和控件状态组合使用规则 225 6.5 加密页面状态 225 6.6 清除页面状态 226 6.7 对...

    ASP.NET编程之道.part1.rar

    谬误19 TextBox控件依靠ViewState保存状态数据 谬误20 必须在页面添加元素才能使用CSS文件中的样式 第3篇 技术细节篇 第5章 必知必会的40个C#语言方面的技术细节 细节01 给C#代码加注释的意义 细节02 装箱和拆箱 ...

    庖丁解牛纵向切入ASP.NET 3.5控件和组件开发技术.pdf

    6.4.1 在禁用视图状态的情况下仍然使用viewstate对象221 6.4.2 istatemanager接口仍然可以在控件状态中使用223 6.4.3 视图状态和控件状态组合使用规则225 6.5 加密页面状态225 6.6 清除页面状态226 6.7 对动态...

    net学习笔记及其他代码应用

    45.swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上? 答:switch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,...

    asp.net教学讲义

    5.11 使用Viewstate保持窗体状态 90 5.12 把视图状态用作数据存储 91 5.12.1 视图状态应用示例 92 5.13 利用查询字符串传递数据 92 5.14 利用隐藏的窗体字段传递数据 92 5.14 变量的作用域 93 第六章:站点设计 94 ...

    ExtAspNet_v2.3.2_dll

    目标是创建没有ViewState,没有JavaScript,没有CSS,没有UpdatePanel,没有WebServices的Web应用程序。 支持的浏览器: IE 7.0+, Firefox 3.0+, Chrome 2.0+, Opera 9.5+, Safari 3.0+ 注:ExtAspNet基于一些开源...

Global site tag (gtag.js) - Google Analytics