页面的视图状态(Ⅰ)

作者在 2007-11-03 16:48:00 发布以下内容

让我们分析一种典型情况。假设页面有一个文本框服务器控件。我们所期望的是,当页面回发时,该文本框服务器控件自动地被赋予客户端设置的值。然而,为了满足这种相当普通的需求,我们不需要视图状态。考虑如下页面:

<% @Page language="c#" %>

<form runat="server">

<asp:textbox runat="server" enableviewstate="false"

id="theInput" readonly="false" text="Type here" />

<asp:checkbox runat="server" enableviewstate="false"

id="theCheck" text="Check me" />

<asp:button runat="server" text="Click" onclick="OnPost" />

</form>

显然,即使禁用了几个控件的视图状态,该页面的行为也是有状态的。原因在于该页面使用了两个服务器控件:TextBox和CheckBox,它们的关键属性(Text和Checked)根据用户设置的值进行更新。对于这些属性,投递的值将覆盖视图状态可能已经设置的任何设置。因而,如果只对持久地存储这些属性感兴趣,则根本不需要视图状态。

同样,.aspx文件中设计时设置的所有控件属性以及在会话期间不会发生变化的所有控件属性,不需要启用视图状态。如下代码说明了这一点:

<asp:textbox runat="server" id="TextBox1" Text="Some text"

MaxLength="20" ReadOnly="true" />

我们不需要用视图状态来使TextBox的Text属性保持最新;只要这些属性在页面的生命期会改变其值,如ReadOnly或MaxLength属性,就不需要使用视图状态来更新它们。如果这两个属性在页面生命期内保持不变,也不需要对它们启用视图状态。

那么,什么时候真正需要视图状态呢?

每当页面要求在页面生命期内更新附属控件的属性(不受投递的值支配),就需要视图状态。在这种情况下,“已更新的(updated)”表示原始值发生变化——要么是默认值,要么是设计时赋给该属性的值。考虑如下窗体:

<script runat="server">

void Page_Load(object sender, EventArgs e)

{

if (!IsPostBack)

theInput.ReadOnly = true;

}

</script>

<form id="form1" runat="server">

<asp:textbox runat="server" id="theInput" text="Am I read-only?" />

<asp:button ID="Button1" runat="server" text="Click" onclick="OnPost" />

</form>

第一次加载该页面时,文本框是只读的。接着,单击该按钮以回发页面。如果视图状态被启用,则页面如期望的那样起作用,并且文本框保持只读。如果禁用该文本框的视图状态,则恢复ReadOnly属性的原始设置——这里为false。

一般而言,只要状态信息可以从客户端或运行时环境中推断出,就不需要视图状态。相反,如果状态信息不能动态地推断出,并且不能保证页面回发时正确恢复所有属性,则必须启用视图状态。这正好是视图状态以下载和上传额外的字节为代价能做到的。要节省那些字节,就必须提供一种替代方法。

提示

通过使用布尔属性EnableViewState,可以以编程的方式启用和禁用页面及其各控件的视图状态。

禁用视图状态也会提出一些难于诊断和修复的更微妙的问题,尤其在使用第三方控件或者可以访问源代码的控件时。实际上,一些ASP.NET控件不仅可以把编程接口的官方属性保存到视图状态中,而且还可以把内部属性以及标记为保护的(甚至是私有的)行为属性保存到视图状态中。不幸的是,对于这些控件,没有禁用视图状态的选项。但是ASP.NET 2.0用控件状态(control state)克服了这一缺陷。

 

我们可以做个实验,在Button1_Click事件中,编写代码:

ListBox.Items.Add(”客户端点击按钮一次!”);

此时运行该应用程序,单击网页上的按钮,在ListBox中会添加内容,不断地单击,内容则不断添加。如果我们将ListBox的EnableViewState属性改为false时,不断单击按钮,则只能添加一次。

这样有什么好处呢?如果我们在开发Web应用程序时,某些控件是不需要接受用户的操作或只需要接受一次操作的时候,我们可以将这些控件的EnableViewState属性改为false,这样可以优化我们的程序,提高网络访问的速度。

asp.net | 阅读 2448 次
文章评论,共2条
ChenMo
2007-11-18 23:17
1
控件的 ViewState 称呼其为“控件状态”,
控件状态与页面视图状态是指存放在页面中的状态信息(使用 <input type = "hidden" ...>)。

视图状态使用的是 ViewState,
用于保存页面所需持久使用的对象。
因为页面的生存周期非常断,并且 Web 是无连接状态,
页面内使用的某些对象无法保存下来,
页面被加载完成后,这些对象面临被“屠杀”。
要保存这些对象的方法可以使用 Application,
Application 不足之处是范围太广,并且所有用户全局共享,
使用 Session 可以弥补 Application 使用上的不足,
然而,当某个对象仅服务于当前页面,或者说,它仅在本页使用的话,
使用 Session 则徒增服务器的负担,
视图状态(ViewState)可以为此提供解决办法,
ViewState 内的对象仅对本页有效。

protected ArrayList al = null;
protected void Page_Load(object sender, EventArgs e)
{
   if (!IsPostBack)
   {
      al = new ArrayList();
      al.Add("Asp.NET");
      al.Add("软件工程");
      al.Add("SQL Server");
      al.Add("HTML");

      //存入到视图状态
      ViewState["course"] = al;
   }
   al = ViewState["course"] as ArrayList;
}

protected void Button1_Click(object sender, EventArgs e)
{
   // 若没有在 Page_Load()函数内重新设置
   // al = Viewstate["course"] as ArrayList
   // 下面这句将引发异常,因为 al 在加载完后已经
   // 销毁了(但是使用视图状态,该 al 对象先
   // 被序列化然后经过 base64 编码存入到页面的
   // <input type="hidden" ...> 标记中)。
   Label1.Text = al[0].ToString();
}
ChenMo
2007-11-18 23:26
2
在上一评论中,
我对“页面视图状态”及“控件视图状态”两个概念上作了区别。
页面视图状态的概念范畴比控件视图状态要广一些,
例如 TextBox 的视图状态可称作“控件状态”。
控件的视图状态由 asp.net 系统维护(可以使用 EnableViewState 来关闭指定控件的状态),
而视图状态(ViewState)则可用来保存我们想保存的对象,
而不是 TextBox.Text 这类控件的状态。
游客请输入验证码
浏览92275次