删除页面加载控件时的ASP.NET问题

时间:2012-10-02 23:12:50

标签: c# asp.net

我有以下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;
        }
    }
}

当我在查询字符串中运行没有remove-dummy参数的应用程序并从intDropDownList中选择一些值并单击“提交”按钮时,所选值将相应地显示在selectedValueLabel中。

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

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

2 个答案:

答案 0 :(得分:2)

嗯,好像很奇怪。我通过将删除控件的代码移动到Page的PreInit事件:

来实现它
protected void Page_PreInit(object sender, EventArgs e)
{
    if (this.Request["remove-dummy"] != null)
    {
        this.Controls.Remove(this.dummyLabel);
    }
}

答案 1 :(得分:1)

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

详细说明:

首先研究以下文章:

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

ASP.NET Page events and ViewState handling

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

  1. 第一次使用查询字符串参数remove-dummy = 1。
  2. 请求页面
  3. 在Page_Load事件声明中,删除了控制dummyLabel。
  4. 在SaveStateComplete事件之前,保存ViewState。控制树中没有控制dummyLabel,因此不会保存其ViewState。
  5. 点击提交按钮。
  6. 在InitComplete和PreLoad事件之间,ViewState被加载。这是因为控制树现在包含dummyLabel(dummyLabel在Load事件中被删除)和 ASP.NET以递归方式将ViewState加载到页面控制树中失败,因此它就会中断。我的假设是ViewState和Page控件树是紧密耦合的,并且由于这种紧密耦合,递归ViewState加载失败。
  7. 支持这个理论的另一个情况是:如果你将dummyLabel放在页面的最末端,问题就不会再发生了,因为在dummyLabel之前的页面控制树中的所有其他控件已经从ViewState中选择了正确的值(ViewState结构和页面控制树紧密耦合)。如果在dummyLabel之后有更多控件,则它们的ViewState加载将失败。

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