0

私は次のIndex.aspxWebフォームを持っています:

<%@ 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から値を選択して[送信]ボタンをクリックすると、選択した値が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の処理

では、宣言型のコントロールdummyLabelが削除されるとどうなりますか?プロセスは次のとおりです。

  1. ページは、クエリ文字列パラメータremove-dummy=1で初めて要求されます。
  2. Page_Loadイベントでは、宣言型のコントロールdummyLabelが削除されます。
  3. SaveStateCompleteイベントの前に、ViewStateが保存されます。コントロールツリーにはコントロールdummyLabelがないため、そのViewStateは保存されません。
  4. [送信]ボタンをクリックします。
  5. InitCompleteイベントとPreLoadイベントの間に、ViewStateがロードされます。これは、コントロールツリーにdummyLabelが含まれるようになり(LoadイベントでdummyLabelが削除された後)、ASP.NETがViewStateをPageコントロールツリーに再帰的にロードできないために機能しなくなります。私の仮定では、ViewStateとPageコントロールツリーは密結合であり、この密結合の結果として、再帰的なViewStateの読み込みは失敗します。

この理論を裏付けるもう1つの状況:dummyLabelをページの最後に配置すると、dummyLabelの前にあるページコントロールツリーの他のすべてのコントロールがすでにViewState(ViewState構造)から正しい値を選択しているため、問題は発生しなくなります。とページコントロールツリーは緊密に結合されています)。ダミーラベルの後にさらにコントロールがある場合、それらのViewStateのロードは失敗します。

この問題を解決するには、削除する必要のあるすべての宣言型コントロール(ASPXファイルで定義)を、ViewStateの読み込みが行われる前に(InitCompleteイベントまたはその前のその他のイベントで)削除する必要があります。

于 2012-10-03T20:45:50.757 に答える