让我们分析一种典型情况。假设页面有一个文本框服务器控件。我们所期望的是,当页面回发时,该文本框服务器控件自动地被赋予客户端设置的值。然而,为了满足这种相当普通的需求,我们不需要视图状态。考虑如下页面:
<% @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,这样可以优化我们的程序,提高网络访问的速度。