Постоянный динамический контроль в ASP.Net - PullRequest
7 голосов
/ 27 апреля 2011
<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...

Есть ли способ создать динамические элементы управления, которые будут сохраняться даже после обратной передачи? Другими словами, когда пользователь нажимает кнопку, генерируется новое текстовое поле, и при повторных щелчках первое остается, а второе генерируется. Как я могу сделать это, используя asp.net? Я знаю, что если я смогу создать элементы управления в событии page_init, они сохранятся, но я не знаю, возможно ли обработать нажатие кнопки до того, как произойдет page_init, поэтому должен быть другой способ.

Ответы [ 2 ]

4 голосов
/ 27 апреля 2011

Да, это возможно.Один из способов сделать это с использованием чисто ASP.NET (что похоже на то, что вы просите) состоит в том, чтобы вести подсчет добавленных вами элементов управления TextBox (сохраняя это значение в ViewState) и воссоздаватьTextBox элементы управления в событии Page_Load.Конечно, в настоящее время большинство людей, вероятно, использовали бы Javascript или jQuery для обработки этой задачи на стороне клиента, но я собрал быстрый пример, чтобы продемонстрировать, как он работает с обратными ссылками:

Первая страница:

<%@ 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, чтобы быстро продемонстрировать, как читать значения из текстовых полей.

РЕДАКТИРОВАТЬ Я обновил пример добавления панели, содержащей TextBox и кнопку «Удалить».Хитрость в том, что кнопка «Удалить» не удаляет панель контейнера, она просто делает ее невидимой.Это делается для того, чтобы все идентификаторы элементов управления были одинаковыми, чтобы введенные данные оставались с каждым TextBox.Если бы мы полностью удалили TextBox, данные после того, как TextBox был удален, сместились бы вниз на один TextBox при следующей обратной передаче (просто, чтобы объяснить это немного яснее, если у нас есть txt1, txt2 и txt3, и мы удалим txt2,при следующей обратной передаче мы создадим два текстовых поля, txt1 и txt2, и значение, которое было в 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;
    }
}
1 голос
/ 27 апреля 2011

Я прочитал статью Скотта Митчелла, в которой объясняется, что ViewState сохраняет только измененное состояние элемента управления после обратной передачи, а не сами элементы управления.У меня не было вашего точного сценария, но проект, над которым я работал, требовал динамически добавлять пользовательские элементы управления, и мне приходилось добавлять их при каждой обратной передаче.В этом случае все еще полезно создавать их в Init, чтобы они могли сохранять свое состояние.Вот ссылка: Понимание ASP.NET View State .Проверьте раздел «Просмотр состояния и динамически добавленные элементы управления».

Возможно, вам придется отслеживать все добавляемые элементы управления (например, в состоянии сеанса) и воссоздавать их при обратной публикации.Я только что провел небольшой тест, в котором храню List<string> всех идентификаторов Textbox в сеансе.При обратной передаче я воссоздаю все текстовые поля.

...