Continuous dynamic control in ASP.Net
<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... Is there a way to create dynamic controls that will persist even after postback? In other words, when the user clicks on the button, a new text field will be created, and when pressed again, the first will remain until the second is created. How to do this with asp.net? I know that if I can create controls in the page_init event, they will be saved, but I don’t know if the button can be processed before page_init appears, so there should be another way.
Yes it is possible. One way to do this using pure ASP.NET (which seems to be what you are asking for) would be to keep the number of TextBox controls you added (keeping this value in the ViewState ) and recreate the TextBox in Page_Load event. Of course, at present, most people are likely to use Javascript or jQuery to handle this task on the client side, but I put together a quick example to demonstrate how it works with postbacks:
Main page:
<%@ 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> Code behind:
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 />")); } } } } Because you recreate the controls with each postback, the values entered in the text fields will be saved in every backward direction. I added btnWriteValues_Click to quickly demonstrate how to read values from text fields.
EDIT
I updated the example to add a panel containing a TextBox and a Delete button. The trick here is that the “Delete” button does not remove the container bar, it just makes it invisible. This is to ensure that all control identifiers remain the same, so the entered data remains with each text field. If we completely deleted the TextBox, the data after the deleted TextBox would move one TextBox to the next postback (just to explain it a bit more clearly if we have txt1, txt2 and txt3, and we will delete txt2, on the next callback we create two text fields: txt1 and txt2, and the value that was in txt3 will be lost).
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; } } I read an article by Scott Mitchell explaining that the ViewState only saves the changed control state post-back, not the controls themselves. I did not have your exact script, but in the project I worked on the required dynamically added user controls, and I had to add them with each postback. In this case, it is still useful to create them in Init so that they can maintain their state. Here is the link: Understanding ASP.NET View State . Check the "View Status and Dynamically Added Controls" section.
You may need to track all the controls you add (for example, in session state) and re-create them in the response message. I just did a little test in which I save the List<string> all the text field IDs in the session. In postback, I recreate all text fields.