You don't really need to keep track of your programmatically or dynamically added controls. It's true that somehow someone has to keep track of them, but it's not you who should be doing so.
Understanding the Page Life-cycle in ASP.NET Web Forms is a must for any ASP.NET developer. Sooner or later you'll run into this sort of problems that would be greatly simplified if you really understood the underlying mechanics of the page.
Each time a request is made to the server, the whole page must be assembled from scratch. You can read (please do) on the web the many steps or stages that make up the Page Life-cycle for an ASP.NET page, but for you to have a rough idea on how this works:
- When the request is made, the .aspx file is parsed and a memory source code created from it. This stage is known as the Instantiation stage, and the page's control hierarchy is created at this point.
- After that, page goes through the Initialization phase, in which the page's Init event is fired. This is "the place" to add controls dynamically.
- LoadViewState phase comes next. At this point, the information of the controls that are part of the page's control hierarchy get their "state" updated to make them return to the state they were before the postback. (This stage doesn't happen on the first time the page is accessed, it's a postback-only stage).
- LoadPostData phase is when the data that has been posted to the server (by submitting the form) is loaded into controls. This stage is barely known to beginner ASP.NET developers, because they assume that all "state preservation" that is automatically enforced by ASP.NET engine comes from the magical Viewstate.
NOTE: If you are really serious about this, you can learn A LOT from this guy here: Understanding ASP.NET View State
What you need to remember from all the above now is that: in order for your dynamically generated controls to "have" their data "glued" together into the control's state after submitting the form by clicking this button Then I would have a button they click that would save the textbox values into the database.
, you need to add the controls to the page at each round-trip to the server.
The recommended way of doing so is in the Page_Init
, because it comes before the LoadViewsate and LoadPostData stages where the control's state is populated.
In your case though, you don't know how many controls to add until the user fills that information on the first form submission. So, you need to find a way to add the controls to the page each time the page loads after the user entered the number of desired controls.
NOTE: You could get away with adding the controls on the btnBookQty_Click
and have their data preserved correctly, because ASP.NET "plays catch-up" on the controls, but that's beyond the scope and purpose of this answer.
- Add a private field to act as a boolean flag and to indicate the number of controls to add.
- Create a private method that add the controls into the page, taking as argument the number of controls to add.
- Call that method from within the
Page_Init
event handler, only if the flag dictates that some fields must be added.
- In
btnBookQty
's click event handler set the flag to the number provided by the user of the page, and...
- Call the method to create the dynamically generated controls from within
btnBookQty_Click
.
Here's a template code of what you need. Notice how HowManyControls
property is stored in the Session to "remember" that value across postbacks:
private int HowManyControls {
get
{
if (Session["HowManyControls"] == null) return 0;
else return (int)Session["HowManyControls"];
}
set
{
Session["HowManyControls"] = value;
}
}
protected void Page_Init(object sender, EventArgs e)
{
if (Page.Ispostback && HowManyControls > 0)
{
//generate the controls dynamically
GenerateControls(HowManyControls);
}
}
protected void btnBookQty_Click(object sender, EventArgs e)
{
//get the number of controls to generate dynamically from the user posted values
HowManyControls = Convert.ToInt32(TextBox1.Text);
//generate the controls dynamically
GenerateControls(HowManyControls);
}
protected void btnSaveToDatabase_Click(object sender, EventArgs e)
{
//iterate on the control's collection in pnlBook object.
for (int i = 1; i <= HowManyControls; i++)
{
//save those value to database accessing to the control's properties as you'd regularly do:
TextBox tb = (TextBox)pnlBooks.FindControl("TextBoxTitle" + i.ToString());
TextBox tb2 = (TextBox)pnlBooks.FindControl("TextBoxAuthor" + i.ToString();
//store these values:
tb.Text;
tb2.Text;
}
}
private void GenerateControls(int count)
{
if (count == 0) { return; }
for (int i = 1; i <= count; i++)
{
TextBox tb = new TextBox();
TextBox tb2 = new TextBox();
tb.Text = "Book " + i.ToString() + " Title";
tb2.Text = "Book " + i.ToString() + " Author";
tb.ID = "TextBoxTitle" + i.ToString();
tb2.ID = "TextBoxAuthor" + i.ToString();
pnlBooks.Controls.Add(tb);
pnlBooks.Controls.Add(tb2);
pnlBooks.Controls.Add(new LiteralControl("<br />"));
}
}
EDIT
I had forgotten that ViewState is not available during Page_Init. I've now modified the answer to use Session instead.