7
<asp:Button onclick="Some_event" Text="Add TextBox" ID="id1" runat="server" />
//once clicked:
<asp:TextBox ID="txt1" ......></asp:TextBox>
//when clicked again:
<asp:TextBox ID="txt1" ......></asp:TextBox>
<asp:TextBox ID="txt2" ......></asp:TextBox>
//and so on...

ポストバック後も持続する動的コントロールを作成する方法はありますか? つまり、ユーザーがボタンをクリックすると、新しいテキストボックスが生成され、もう一度クリックすると、最初のテキストボックスが残り、2 番目のテキストボックスが生成されます。asp.net を使用してこれを行うにはどうすればよいですか? page_init イベントでコントロールを作成できれば保持されることはわかっていますが、page_init が発生する前にボタンのクリックを処理できるかどうかはわかりません。したがって、別の方法が必要です。

4

2 に答える 2

4

はい、可能です。純粋に ASP.NET を使用してこれを行う 1 つの方法 (これは、あなたが求めているように思えます) は、TextBox追加したコントロールの数を保持し (その値を に保存)、イベントでコントロールViewStateを再作成することです。もちろん、今日ではほとんどの人が Javascript または jQuery を使用してこのタスクをクライアント側で処理することになるでしょうが、ポストバックでどのように機能するかを示す簡単な例をまとめました。TextBoxPage_Load

表紙:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DynamicControls.aspx.cs" Inherits="MyAspnetApp.DynamicControls" EnableViewState="true" %>
<!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"></head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="btnAddTextBox" runat="server" Text="Add" OnClick="btnAddTextBox_Click" />
        <asp:Button ID="btnWriteValues" runat="server" Text="Write" OnClick="btnWriteValues_Click" />
        <asp:PlaceHolder ID="phControls" runat="server" />
    </div>
    </form>
</body>
</html>

コードビハインド:

using System;
using System.Web.UI.WebControls;

namespace MyAspnetApp
{
    public partial class DynamicControls : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //Recreate textbox controls
            if(Page.IsPostBack)
            {
                for (var i = 0; i < TextBoxCount; i++)
                    AddTextBox(i);
            }
        }

        private int TextBoxCount
        {
            get 
            {
                var count = ViewState["txtBoxCount"];
                return (count == null) ? 0 : (int) count;
            }
            set { ViewState["txtBoxCount"] = value; }
        }

        private void AddTextBox(int index)
        {
            var txt = new TextBox {ID = string.Concat("txtDynamic", index)};
            txt.Style.Add("display", "block");
            phControls.Controls.Add(txt);
        }

        protected void btnAddTextBox_Click(object sender, EventArgs e)
        {
            AddTextBox(TextBoxCount);
            TextBoxCount++;
        }

        protected void btnWriteValues_Click(object sender, EventArgs e)
        {
            foreach(var control in phControls.Controls)
            {
                var textBox = control as TextBox;
                if (textBox == null) continue;
                Response.Write(string.Concat(textBox.Text, "<br />"));
            }
        }
    }
}

ポストバックごとにコントロールを再作成しているため、テキスト ボックスに入力された値はポストバックごとに保持されます。btnWriteValues_Clickテキストボックスから値を読み取る方法を簡単に示すために追加しました。

EDIT
TextBox と Remove Button を含む Panel を追加するように例を更新しました。ここでの秘訣は、Remove ボタンはコンテナ Panel を削除せず、表示されないようにするだけです。これは、すべてのコントロール ID が同じままになるように行われるため、入力されたデータは各 TextBox に残ります。TextBox を完全に削除した場合、削除された TextBox の後のデータは、次のポストバックで TextBox を 1 つ下にシフトします (これをもう少し明確に説明するために、txt1、txt2、および txt3 があり、txt2 を削除すると、次のポストバックでは、txt1 と txt2 の 2 つのテキスト ボックスを作成しますが、txt3 にあった値は失われます)。

public partial class DynamicControls : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.IsPostBack)
        {
            for (var i = 0; i < TextBoxCount; i++)
                AddTextBox(i);
        }
    }

    protected void btnAddTextBox_Click(object sender, EventArgs e)
    {
        AddTextBox(TextBoxCount);
        TextBoxCount++;
    }

    protected void btnWriteValues_Click(object sender, EventArgs e)
    {
        foreach(var control in phControls.Controls)
        {
            var panel = control as Panel;
            if (panel == null || !panel.Visible) continue;
            foreach (var control2 in panel.Controls)
            {
                var textBox = control2 as TextBox;
                if (textBox == null) continue;
                Response.Write(string.Concat(textBox.Text, "<br />"));
            }
        }
    }

    private int TextBoxCount
    {
        get 
        {
            var count = ViewState["txtBoxCount"];
            return (count == null) ? 0 : (int) count;
        }
        set { ViewState["txtBoxCount"] = value; }
    }

    private void AddTextBox(int index)
    {
        var panel = new Panel();
        panel.Controls.Add(new TextBox {ID = string.Concat("txtDynamic", index)});
        var btn = new Button { Text="Remove" };
        btn.Click += btnRemove_Click;
        panel.Controls.Add(btn);
        phControls.Controls.Add(panel);
    }

    private void btnRemove_Click(object sender, EventArgs e)
    {
        var btnRemove = sender as Button;
        if (btnRemove == null) return;
        btnRemove.Parent.Visible = false;
    }
}
于 2011-04-27T01:43:50.647 に答える
1

Scott Mitchell の記事を読みました。ViewState は、実際のコントロール自体ではなく、変更されたコントロールの状態をポストバック全体で保持するだけであると説明しています。正確なシナリオはありませんでしたが、私が取り組んでいたプロジェクトでは、動的に追加されたユーザー コントロールが必要であり、ポストバックごとにそれらを追加する必要がありました。その場合でも、状態を保持できるように Init で作成すると便利です。リンクは次のとおりです: ASP.NET View State を理解する。「View State と動的に追加されたコントロール」セクションを確認してください。

追加するすべてのコントロールを (セッション状態などで) 追跡し、ポストバック時に再作成する必要がある場合があります。List<string>セッション内のすべてのテキストボックス IDを保持する小さなテストを行いました。ポストバック時に、すべてのテキスト ボックスを再作成します。

于 2011-04-27T01:50:06.730 に答える