web-dev-qa-db-ja.com

ASP.NETのUpdatePanelに動的にコントロールを追加するAJAX

私は次の本当に単純なコードを持っています

<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
    <asp:PlaceHolder ID="PlaceHolder1" runat="server">
    </asp:PlaceHolder>
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</ContentTemplate>
</asp:UpdatePanel>

そして、コードビハインド

protected void Button1_Click(object sender, EventArgs e)
{
    Literal literal = new Literal();
    literal.Text = DateTime.Now.ToString();
    literal.ID = DateTime.Now.Ticks.ToString();

    // These both work fine the first time the button is clicked
    // but the second time nothing is added.
    UpdatePanel1.ContentTemplateContainer.Controls.Add(literal);
    PlaceHolder1.Controls.Add(literal);
}

私の問題は、リテラルコントロールが一度しか追加されないことです。私はグーグルとブログサイト(そして本)を精査しましたが、運がありませんでした。何が足りないのですか?

13
Chris S

Asp.netでは、ASPXファイルのコントロールはポストバックごとに自動的に生成されます。作成したコントロールはASPXコードに含まれていないため、フレームワークはそれらを作成しません。 Button1_Clickメソッドを初めて実行するときに、ページに1つのコントロールを追加します。 Button1_Clickメソッドを2回実行すると、別のポストバックが表示され、最初の余分なボタンが忘れられています。したがって、そのポストバックの結果、ボタンが1つ追加されます。

これにより、ボタンをクリックするたびに1つの追加のコントロールが作成されます(ただし、コントロールが再作成されるため、ボタンを押すたびにタイムスタンプが更新されます)。

protected void Button1_Click(object sender, EventArgs e)
{
    int count = 0;

    if (ViewState["ButtonCount"] != null)
    {
        count = (int)ViewState["ButtonCount"];
    }

    count++;
    ViewState["ButtonCount"] = count;

    for (int i = 0; i < count; i++)
    {
        Literal literal = new Literal();
        literal.Text = DateTime.Now.ToString();
        literal.ID = DateTime.Now.Ticks.ToString();

        UpdatePanel1.ContentTemplateContainer.Controls.Add(literal);
        PlaceHolder1.Controls.Add(literal);
    }            
}
23
d4nt

上記の回答に同意しますが、このアプローチでは動的コントロールの状態は保存されません(正確には、状態は保存されますが、ロードされません)。ロードビューステートは、ページライフサイクルのロードイベントセクションで呼び出され、ビューステートに保存された制御値を割り当てます。ただし、この時点までにコントロールが作成されていない場合、以前のデータをロードできないため、状態を維持するには、ロードイベント時またはその前に新しいコントロールを再作成する必要があります。

protected void Page_Load(object sender, EventArgs e)
{
    //PS: Below approach saves state as id is constant, it simply generates a new control with same id hence viewstate loads the value
    if (IsPostBack)
    {
        int count = 0;

        if (ViewState["ButtonCount"] != null)
        {
            count = (int)ViewState["ButtonCount"];
        }

        count++;
        ViewState["ButtonCount"] = count;

        for (int i = 0; i < count; i++)
        {
            TextBox literal = new TextBox();
            //literal.Text = DateTime.Now.ToString();
            literal.ID = "Textbox" + i.ToString();

            //UpdatePanel1.ContentTemplateContainer.Controls.Add(literal);
            PlaceHolder1.Controls.Add(literal);

        }
    }
}

動的にコントロールを追加状態の表示とポストバック

3
SKocheta