3

私はこのトピックについて多くのことを見ましたが、解決策を見つけることができません。1つのイベントで多くのドロップダウンリストを追加しましたが、SelectedIndexChangedevetが起動していません。drplistクリエーターコードは次のとおりです。

foreach (var row in cmdSelectCats.ExecuteReader())
{
    var id = row["ProductCategoryID"].ToString();

    var dropDownStatus = new DropDownList {ID = "DrpStatus-" + id};

    dropDownStatus.Items.Add(new ListItem("Aktif", "1"));
    dropDownStatus.Items.Add(new ListItem("Pasif", "2"));

    dropDownStatus.AutoPostBack = true; 
    dropDownStatus.SelectedIndexChanged += Status_SelectedIndexChanged;

    var tableCell = new TableCell();
    tableCell.Controls.Add(dropDownStatus);
    dropDownStatus.SelectedValue = row["ProductCategoryStatusID"].ToString();
    tableRow.Cells.Add(tableCell);
    TblCatList.Rows.Add(tableRow);
}

そしてもちろん私のイベント:

public void Status_SelectedIndexChanged(object sender, EventArgs e)
{
    //DO SOMETHING
} 

私は何が欠けていますか?

4

3 に答える 3

17

これは一般的な問題であり、ページのライフサイクルに関連しています。

次の質問を見てください。

ボタンの配列のイベントをクリックします

クリックイベント後にボタン配列が消える

ImageButtonを動的に作成する

ここで、動的コントロールを作成するときに覚えておくべき基本的な手順は次のとおりです。

  • PreInitマスターページを使用していない場合は、イベントで動的コントロールを作成する必要があります。マスターページを使用している場合は、Initイベントでコントロールを作成します。
  • ビューステートが適用されると(postイベントで)プロパティが上書きされるため、これらのイベントで各postで変更できるプロパティを設定することは避けてください。
  • ページが投稿されるたびに動的コントロールを作成する必要があります。これは避けてくださいif(!this.IsPostBack) this.CreatemyDynamicControls();
  • PreInitまたはイベントでコントロールを作成するとInit、それらの状態はpostイベントで自動的に設定されLoadCompleteます。つまり、各投稿で再度作成した場合や、明示的に設定しなかった場合でも、コントロールに状態が含まれるようになります。彼らの状態。設計時に作成されたコントロールを処理する場合、この動作は異なることに注意してください。その場合、状態が設定されているイベントはLoadイベントです。
  • イベントサブスクリプションは、PageLoadCompleteまたはが発生しない前に発生する必要があります

MSDNからの次の説明を検討してください

コントロールが実行時に動的に作成される場合、またはデータバインドされたコントロールのテンプレート内で宣言的に作成される場合、それらのイベントは最初はページ上の他のコントロールのイベントと同期されません。たとえば、実行時に追加されるコントロールの場合、InitイベントとLoadイベントは、宣言的に作成されたコントロールの同じイベントよりも、ページのライフサイクルのかなり遅い段階で発生する可能性があります。したがって、インスタンス化されてから、動的に追加されたコントロールとテンプレート内のコントロールは、Controlsコレクションに追加されたイベントに追いつくまで、イベントを次々に発生させます。

上記は私にはそれほど明確ではありませんが、私は次のことを発見しました。以下TextBoxのは設計時に作成されます

    protected void Page_PreInit(object sender, EventArgs e)
    {
        this.txtDesignTextBox1.Text = "From PreInit";
        this.txtDesignTextBox1.Text += DateTime.Now.ToString();
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        this.txtDesignTextBox2.Text = "From Init";
        this.txtDesignTextBox2.Text += DateTime.Now.ToString();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        this.txtDesignTextBox3.Text = "From Load";
        this.txtDesignTextBox3.Text += DateTime.Now.ToString();
    }

一見すると、すべての投稿ですべてのテキストボックスが現在の日付で更新されていると思うかもしれませんが、設計時に作成されたため、ASP.Netページのライフサイクル、つまり状態に厳密に従うため、そうではありません。 PreInitイベントとInitイベントの後にオーバーライドされますが、ビューステートが(イベントで)設定された後にプロパティが更新されるtxtDesignTextBox3ため、すべての投稿でのみが更新されます。TextLoad

ただし、動的コントロールでは動作が異なります。MSDNの説明を覚えておいてください。

実行時に追加されるコントロールの場合、InitイベントとLoadイベントは、ページのライフサイクルのかなり後の段階で発生する可能性があります

次のことを考慮してください。

    protected void Page_PreInit(object sender, EventArgs e)
    {
        var textBox = new TextBox { Text = "From PreInit", Width = new Unit("100%") };
        textBox.Text += DateTime.Now.ToString();
        this.myPlaceHolder.Controls.Add(textBox);
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        var textBox = new TextBox { Text = "From Init", Width = new Unit("100%") };
        textBox.Text += DateTime.Now.ToString();
        this.myPlaceHolder.Controls.Add(textBox);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        var textBox = new TextBox { Text = "From Load", Width = new Unit("100%") };
        textBox.Text += DateTime.Now.ToString();
        this.myPlaceHolder.Controls.Add(textBox);
    }

この場合、コントロールの動作はわずかに異なります。この場合、各投稿で、イベントで作成されたコントロールでさえも、コントロールが更新されることはありません。Load

その理由は、それらのライフサイクルイベントがページライフサイクルのかなり後の方で発生するためです。つまり、Loadイベントの後でも状態が上書きされます。

これを解決するには、イベントを使用できます。LoadCompleteこのイベントでは、動的コントロールの状態を変更できます。

    protected void Page_LoadComplete(object sender, EventArgs e)
    {
        var textBox = new TextBox { Text = "From LoadComplete", Width = new Unit("100%") };
        textBox.Text += DateTime.Now.ToString();
        this.myPlaceHolder.Controls.Add(textBox);
    }

この場合、状態は各投稿で更新されます。

ただし、イベントの前に動的制御イベントをサブスクライブする必要があることを考慮してください。そうしないと、LoadCompleteイベントは発生しません。

...私はこの種の行動が嫌いなことを知っているので、MVCが大好きです

設計時に作成されたコントロールのクイックリファレンスとして:およびイベントの、イベントの前にLoadViewStateメソッドがどのように呼び出されるかに注意してください。このイベントでは、コントロールのビューステートにアクセスできるため、イベントは安定していると見なされます。また、メソッドはポストバックを引き起こした制御イベントを表していることに注意してください。これは、、、などです。このイベントはイベントのに処理されます。PreInitInitLoadLoadRaisePostBackEventSelectedIndexChangedClickLoad

ここに画像の説明を入力してください

完全な詳細仕様については、MSDNページのライフサイクルドキュメントをお読みください。

于 2012-06-20T19:46:54.413 に答える
1

私は通常、これがページのライフサイクルの問題によって引き起こされるのを見てきました。イベントが発生したときにのみコントロールが作成される場合、インデックス変更イベントが発生したときに、ポストバックでコントロールをバインドするためのコントロールは存在しません。

例:

  1. MyEventが発生します。ドロップダウンが作成されました。イベントハンドラーが指定されました。
  2. IndexChangedイベントがトリガーされました。ページがリロードされます。ドロップダウンが見つかりません。起動できません。

.NETがイベントを処理しようとする前に、ドロップダウンが作成されていることを確認する必要があります。

于 2012-06-20T18:51:06.450 に答える
-4

不足しています:
1-SaveViewStateを
オーバーライドします2-LoadViewStateをオーバーライドします

この質問のサンプルコードを提供します。私はそれをテストします。それは仕事です。

ASPX:

<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<div id="myDiv" runat="server">
</div>
<asp:Label ID="lblDescription" runat="server"></asp:Label>
</form>

コードビハインド:

public partial class Default : System.Web.UI.Page
    {
        private List<string> values = new List<string>();

        protected void Page_Load(object sender, EventArgs e)
        {

        }        

        protected override object SaveViewState()
        {
            object baseState = base.SaveViewState();            
            object[] allStates = new object[2];
            allStates[0] = baseState;
            allStates[1] = values;
            return allStates;
        }

        protected override void LoadViewState(object savedState)
        {
            object[] myState = (object[])savedState;
            if (myState[0] != null)
                base.LoadViewState(myState[0]);
            if (myState[1] != null)
            {
                values = (List<string>)myState[1];
                MyRender();
            }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                DropDownList ddl = new DropDownList();
                ddl.ID = "ClientID" + i;

                ddl.Items.Add("Item 1");
                ddl.Items.Add("Item 2");
                ddl.AutoPostBack = true;                
                values.Add(ddl.SelectedValue);

                myDiv.Controls.Add(ddl);
            }
        }

        private void MyRender()
        {
            for (int i = 0; i < values.Count; i++)
            {
                DropDownList ddl = new DropDownList();
                ddl.ID = "ClientID" + i;

                ddl.Items.Add("Item 1");
                ddl.Items.Add("Item 2");
                ddl.AutoPostBack = true;
                ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged);

                myDiv.Controls.Add(ddl);
            }
        }

        void ddl_SelectedIndexChanged(object sender, EventArgs e)
        {
            lblDescription.Text = ((DropDownList)sender).ID + ": Selected Index Changed";
        }
    }
于 2012-06-20T20:31:07.620 に答える