ListBox 实现了 IPostBackDataHandler,但当 EnableViewState 设置为 false 时,为什么它不能像 TextBox 一样保持其状态?

ListBox implements IPostBackDataHandler but why can't it maintain its state like a TextBox when EnableViewState is set to false?

在这篇post、Understanding ASP.NET View State中,作者是这样说的:

It is a common misconception among developers that view state is somehow responsible for having TextBoxes, CheckBoxes, DropDownLists, and other Web controls remember their values across postback. This is not the case, as the values are identified via posted back form field values, and assigned in the LoadPostData() method for those controls that implement IPostBackDataHandler.

因此,当我禁用 TextBox 的视图状态时,它仍然会在 post 后面保留其文本值,根据上面的描述,这是正确的。

但是,当我禁用同样实现 IPostBackDataHandler 的 ListBox 的视图状态时,它不会在 postbacks 中保留其状态。例如,下面提供的代码应该在单击按钮(在同一网络表单中)时添加重复项目(使用空事件处理程序),但它没有。

我是不是漏掉了什么?

protected void Page_Load(object sender, EventArgs e)
{
        lbox.Items.Add("1");
        lbox.Items.Add("2");
        lbox.Items.Add("3");
}

在您引用的句子中,单词"values"特指用户提交表单时浏览器向服务器发送的表单字段值post。这些值由 HTML specification:

定义
  • 对于呈现为 <input type="text"> 元素的 TextBox 控件,浏览器 post 是在文本框中输入的文本。 TextBox 控件的 IPostBackDataHandler implementation 读取此值并将其分配给文本 属性.
  • 对于呈现为 <select> 元素的 ListBox 控件,浏览器 post 是每个选定 <option>value。 (浏览器 而不是 post 整个 <option> 元素列表。)ListBox 控件的 IPostBackDataHandler implementation 读取这些值并且 selects/deselects 每个ListItem 相应地。 (实施 添加任何项目。)

重要的一点是,无论视图状态是启用还是禁用,浏览器 post 都会设置这些值。因此,即使禁用视图状态,TextBox.TextListBox.SelectedValue 也会保留用户在 post 后的输入。

但是,浏览器通常 post 无法编辑的任何其他内容(例如 ListBox 中的选项列表)都需要启用视图状态才能在 post 后台保留。

我想可以从下图中找到答案。 (经测试)

正如您在 步骤 1 中注意到的那样,lblMessage.Text 中的值是 "Hello World!",没有任何 Raise PostBack Event Stage,因此该值被保留原样。

<asp:Label runat="server" ID="lblMessage" 
  Font-Name="Verdana" Text="Hello, World!"></asp:Label>
<br />
<asp:Button runat="server" 
  Text="Change Message" ID="btnSubmit"></asp:Button>
<br />
<asp:Button runat="server" Text="Empty Postback"></asp:Button>

And the code-behind class contains the following event handler for the Button's Click event:

private void btnSubmit_Click(object sender, EventArgs e)
{
  lblMessage.Text = "Goodbye, Everyone!";
}

接下来,对于文本框,即使您禁用特定控件/整个页面的视图状态,保存的是 PostBack 事件,这就是为什么如果您查看 步骤 3,之前的PostBack作为Load View State Stage的一部分加载,这使得已经实例化的"Hello World!"被覆盖。

顺便说一句,这个解释只适用于不使用数据源的控件事件,其他需要数据源的控件似乎在文档中隐式定义。