不明白为什么在更改内容时ViewState的大小没有增加?

时间:2011-06-04 11:09:58

标签: c# viewstate asp.net-4.0

我以为我理解了ViewState,但这有点奇怪。

我有一个包含1000个标签和文本框的页面,如下所示:

<dt>
   <asp:Label runat="server" ID="Label1" AssociatedControlID="TextBox1">Label1</asp:Label>
</dt>
<dd>
   <asp:TextBox runat="server" ID="TextBox1"></asp:TextBox>
</dd>

所有增加1.我在顶部添加了一个按钮:

<asp:Button runat="server" ID="PostBack" Text="Post it all back!" OnClick="ChangeValues"/>

,相应的代码是:

protected void ChangeValues(object sender, EventArgs e)
{
   for (int i = 1; i <= 1000; i++)
   {
      string textBoxId = "TextBox" + i;
      ((TextBox)Page.FindControl(textBoxId)).Text = textBoxId;
   }
}

所以我理解的是:

  1. 首页加载,控件最初设置,因此没有创建控件视图状态
  2. 在回发时,按钮单击正在修改控件。因此,在生成ViewState时,.NET会意识到文本已从默认值更改并在viewstate中记录。
  3. 现在对于1000个控件,你会发现它相当大,比这更大:

    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNjYzODc0MDE1ZGQRGHqYtZTbbkevIfg33I4Wja+xfz0at0+fDMS72BtZNA==" />
    

    我想我在这里错过了一招。我已打开Trace=true,并注意到所有ViewState仍为0字节。 EnableViewStateViewStateMode未在<@Page指令中声明,因此ViewState已启用并正在运行。

    任何人都可以帮助我理解为什么我误解了这是如何工作的?

2 个答案:

答案 0 :(得分:2)

也许是因为TextBox的Text属性不需要保存到ViewState,因为它将呈现给页面并使用发布数据回发。

如果你看一下使用Reflector的TextBox的实现,你会发现它有一个属性SaveTextViewState来控制是否需要将Text属性保存到ViewState:

protected override object SaveViewState()
{
    if (!this.SaveTextViewState)
    {
        // This means the Text property will not be saved to ViewState
        this.ViewState.SetItemDirty("Text", false);
    }
    return base.SaveViewState();
}

如果需要保存ViewState(例如TextBox不可见),SaveTextViewState将返回true,Text属性将保存到ViewState。

<强>更新

根据Reflector,SaveTextViewState属性(用于确定Text是否需要持久化到ViewState的属性)的实现如下:

private bool SaveTextViewState
{
    get
        {
            if (this.TextMode == TextBoxMode.Password) return false;
        }
        if (((base.Events[EventTextChanged] == null) && 
              base.IsEnabled) && 
              ((this.Visible && !this.ReadOnly)  && 
              (base.GetType() == typeof(TextBox))))
        {
            return false;
        }
        return true;
    }
}

即。如果Text不是密码文本框并且满足以下任何条件,则TextBox会持久保存到ViewState:

  • 存在TextChanged事件的处理程序(在这种情况下,它需要原始值来检测文本是否已更改)

  • 禁用控件(在这种情况下,文本不会被回发)

  • 控件不可见(在这种情况下,它不会被渲染)

  • 控件是只读的(文本不会回发)

  • 控件类型不是{{1}}(不要通过抑制ViewState进行优化,因为这可能会影响派生控件的实现)。

本质上是一种优化,如果确定不需要ViewState,则会抑制它。

答案 1 :(得分:0)

答案是实施IPostBackEventHandlerTextbox, Checkbox等实施的控件将保留状态even after disabling the viewstate。原因是在Load Postback Data阶段,这些控件将从Posted back form获取状态信息。

但是像label这样没有实现IPostBackEventHandler的控件将不会从发布的数据中获取任何状态信息,因此完全依赖于viewstate来维护状态。