0

我有以下 Index.aspx 网络表单:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="ProblematicWebApplication.Index" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <asp:Label ID="dummyLabel" runat="server" Text="This is dummy label." />
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="intDropDownList" runat="server"/>
        <br />
        <asp:Button Text="Submit" OnClick="OnSubmitClicked" runat="server"/>
        <br />
        Selected value: <asp:Label ID="selectedValueLabel" runat="server" />
    </div>
    </form>
</body>
</html>

Index.aspx.cs 文件后面的代码如下:

using System;
using System.Linq;

namespace ProblematicWebApplication
{
    public partial class Index : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                this.intDropDownList.DataSource = Enumerable.Range(0, 11).ToArray();
                this.intDropDownList.DataBind();
            }

            if (this.Request["remove-dummy"] != null)
                this.Controls.Remove(this.dummyLabel);
        }

        protected void OnSubmitClicked(object sender, EventArgs e)
        {
            this.selectedValueLabel.Text = this.intDropDownList.SelectedValue;
        }
    }
}

当我在查询字符串中没有删除虚拟参数的情况下运行我的应用程序并从 intDropDownList 中选择一些值并单击提交按钮时,所选值相应地显示在 selectedValueLabel 中。

但是,如果我在查询字符串中使用 remove-dummy=1 参数运行我的应用程序,则会删除 dummyLabel。现在,当我从 intDropDownList 中选择一些值并单击提交按钮时,所选值未正确写入 selectedValueLabel 并且 intDropDownList 中的所有项目都被删除。

有人可以向我解释为什么会这样吗?为什么删除不相关的 dummyLabel 控件会影响 intDropDownList 控件?

4

2 回答 2

2

嗯,好像很奇怪。我通过将删除控件的代码移动到页面PreInit事件中来使其工作:

protected void Page_PreInit(object sender, EventArgs e)
{
    if (this.Request["remove-dummy"] != null)
    {
        this.Controls.Remove(this.dummyLabel);
    }
}
于 2012-10-02T23:15:00.613 回答
1

在上一页加载中删除 dummyLabel 后,ViewState 加载似乎在回发中失败。

细节:

首先研究以下文章:

下图显示了重要的 ASP.NET 页面事件以及 ViewState 处理之间发生的位置。

ASP.NET 页面事件和 ViewState 处理

那么当声明性 Control dummyLabel 被删除时会发生什么?这是一个过程:

  1. 首次使用查询字符串参数 remove-dummy=1 请求页面。
  2. 在 Page_Load 事件中,声明性控件 dummyLabel 被删除。
  3. 在 SaveStateComplete 事件之前,ViewState 被保存。控件树中没有控件 dummyLabel,所以它的 ViewState 不会被保存。
  4. 单击提交按钮。
  5. 在 InitComplete 和 PreLoad 事件之间,ViewState 被加载。这是它中断的地方,因为控制树现在包含 dummyLabel(dummyLabel 在 Load 事件之后被删除)并且ASP.NET 无法将 ViewState 递归加载到 Page control tree。我的假设是 ViewState 和 Page 控制树是紧密耦合的,并且由于这种紧密耦合,递归 ViewState 加载会失败。

支持这一理论的另一种情况:如果您将 dummyLabel 放在页面的最后,问题就不会再发生了,因为页面控件树中的所有其他控件在 dummyLabel 之前已经从 ViewState(ViewState 结构和页面控制树是紧密耦合的)。如果 dummyLabel 之后有更多控件,它们的 ViewState 加载将失败。

要解决此问题,必须在 ViewState 加载发生之前删除所有应删除的声明性控件(在 ASPX 文件中定义) - 在 InitComplete 事件或之前的任何其他事件中。

于 2012-10-03T20:45:50.757 回答