First off we will create a new tab that will contain a button control and a repeater that will contain a placeholder control
<cc1:TabPanel ID="tabDemo" runat="server" HeaderText="Textbox Control Demo">
<asp:Repeater ID="rptDemo" runat="server">
<asp:PlaceHolder ID="phDemo" runat="server"></asp:PlaceHolder>
<asp:Button runat="server" ID="btnAddTextBox" Text="Add a new textbox" OnClick="AddTextBox" />
The idea are working with is the following. The placeholder will contain only 1 control at a time, be a composite user control or in this example a textbox control. We will bind a generic list of strings to the repeater and using the ItemCreated event of the repeater, we will program it to create a textbox and put the contents of the string item into the text property of the textbox.
We will also create a page property that returns a generic list of strings. This will be got from the repeater but looping through each item in the Items collection and finding the textbox in the placeholder control and getting its text property. Each time we want to add a new textbox, we will use this page property to get all the current values and then add a new blank string to this list. After we have done that, we will rebind the repeater with the new list. By using this method to create our textboxes, we can store the values easily and manage state easily as well.
So now the page property
private List<string> CurrentTextBoxData
List<string> items = new List<string>();
foreach (RepeaterItem item in rptDemo.Items)
TextBox textBox = (TextBox) item.FindControl("phDemo").Controls;
What we are doing here, is firstly creating a new list on line 5. Then we are looping through all the RepeaterItems in the Items collection of the Repeater. In the item, we are finding the textbox that we have added. We do this by using the FindControl method of the RepeaterItem to find the specified placeholder control and then accessing its Controls collection and casting that object as a textbox control. We dont need to cast the placeholder control because it inherits from the Control object which has a Controls collection. Once we have that textbox we add the value of the Text property to our list. Once we have looped through all the RepeaterItems we will return the list.
Now to the OnClick event handler of the button which will add a new textbox
protected void AddTextBox(object sender, EventArgs e)
var currentData = CurrentTextBoxData;
rptDemo.DataSource = currentData;
So we first create a new list called currentData and assign it to the value of CurrentTextBoxData which is the page property we created just before. We then add a blank string to the list. Once we have done that, we set the repeater’s data source to the new list and then databind it.
Why do we create a new list and what doesn’t the CurrentTextBoxData property have a setter?. The answer to both these questions is the following. Firstly we are using the repeater as a date store to store the current values in the textbox. Each time we want to add to it, we should get a copy of the current values and add the new value to this copied list. Finally we will replace the current values with the new copy of the values. So in this way, there is no need for a setter per se because the databind event acts as the setter since it places all the values in the repeater.
We will continue with the ItemCreated event of the repeater. You will need to either manually add the event to the repeaters declaration in the ASPX page or add it in the Page.OnInit entry in the code behind.
private static void RptDemoItemCreated(object sender, RepeaterItemEventArgs e)
var data = (string) e.Item.DataItem;
var textBox = new TextBox
Text = data
var placeholder = (PlaceHolder) e.Item.FindControl("phDemo");
Firstly, we cast the DataItem to a string. We know this is a string because that is what are binding to the repeater control. We then create a new instance of a textbox control and set its text property to the string in the DataItem. Now we create a placeholder and assign it to the placeholder in the repeater item using the FindControl method. We then add our newly created textbox to the placeholder. This how we dynamically create our controls.
Running this will now allow you to click the button and that will add a new control. You can edit the values of the textboxes and they will survive postback because each time we need to create new ones, we get the current values and then recreate them all again.
The next post will deal with adding dynamic databound user controls and also how to remove dynamic controls as well as bubbling events up from your user control to be handled by the repeater.
The code bits for all these posts can be found in the first post here