Few months ago I wrote a series of blog posts about creating a dynamic rows in GridView and Table. In this example I'm going to demonstrate how to build a simple form that allows you to create a dynamic row using the standard ASP Repeater control.
To get started, let’s grab a Repeater control from the Visual Studio Toolbox and place it in the WebForm. The mark up should look something like this:
<!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">
<title>Building a Dynamic Repeater Rows</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<asp:Label ID="LabelRowNumber" Text='<%# DataBinder.Eval(Container.DataItem, "RowNumber") %>' runat="server" />
<asp:TextBox ID="TXTName" runat="server" Width="100px"></asp:TextBox><br />
<asp:TextBox ID="TXTComments" TextMode="MultiLine" Height="50px" Width="200px" runat="server"></asp:TextBox><br />
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="BTNPost" runat="server" Text="Post" OnClick="BTNPost_Click" /><br />
</div>
</form>
</body>
</html>
Just for the purpose of this example, I want to create a form that would allow me to enter a name with comments. So as you can see I have added an ItemTemplate within the Repeater and set up some TextBox there for me enter the name and comments. You will also noticed that the Post Button is being placed outside the Repeater control because we don't want to repeat that Button for each row.
Now let’s switch to the Code behind part of the webform.
As you may know, a Data Representation control such as Repeater will not show up in the page once there is no data associated on it. So the first thing we need here is to set an initial data in the Repeater control. To do this, we can use a DataTable for binding our GridView and set up some dummy data.
Here’s the code block below:
private void SetInitialRow() {
DataTable dt = new DataTable();
DataRow dr = null;
//Create DataTable columns
dt.Columns.Add(new DataColumn("RowNumber", typeof(string)));
dt.Columns.Add(new DataColumn("Name", typeof(string)));
dt.Columns.Add(new DataColumn("Comments", typeof(string)));
//Create Row for each columns
dr = dt.NewRow();
dr["RowNumber"] = 1;
dr["Name"] = string.Empty;
dr["Comments"] = string.Empty;
dt.Rows.Add(dr);
//Store the DataTable in ViewState for future reference
ViewState["CurrentTable"] = dt;
//Bind the Repeater with the DataTable
Repeater1.DataSource = dt;
Repeater1.DataBind();
}
As you can see, we defined 3 (three) Columns in the DataTable called RowNumber, Name and Comments. The RowNumber column will serve as the key for generating the rows in the Repeater. Noticed that for Name and Comments columns, I have assigned an empty value for them since the Repeater will be generated for the first time. You also noticed that I stored the DataTable in ViewState so that we can reference the current data associated within the DataTable when it postbacks.
Now lets call the method above in Page_Load event:
protected void Page_Load(object sender, EventArgs e){
if (!IsPostBack) {
SetInitialRow();
}
}
Now when we run the page on the brower you will see something like below:

Now let us create the method for generating the rows when clicking the Button. Here are the code blocks below:
private void AddNewRow() {
int rowIndex = 0;
if (ViewState["CurrentTable"] != null) {
DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
DataRow drCurrentRow = null;
if (dtCurrentTable.Rows.Count > 0) {
for (int i = 1; i <= dtCurrentTable.Rows.Count; i++) {
//extract the TextBox values
TextBox tbName = (TextBox)Repeater1.Items[rowIndex].FindControl("TXTName");
TextBox tbComments = (TextBox)Repeater1.Items[rowIndex].FindControl("TXTComments");
//Create new row in DataTable and set its values
drCurrentRow = dtCurrentTable.NewRow();
drCurrentRow["RowNumber"] = i + 1;
dtCurrentTable.Rows[i - 1]["Name"] = tbName.Text;
dtCurrentTable.Rows[i - 1]["Comments"] = tbComments.Text;
rowIndex++;
}
//add the new row to the current DataTable
dtCurrentTable.Rows.Add(drCurrentRow);
//store the current DataTable in ViewState
ViewState["CurrentTable"] = dtCurrentTable;
//rebind the Repeater with the updated DataTable
Repeater1.DataSource = dtCurrentTable;
Repeater1.DataBind();
}
}
else {
Response.Write("ViewState is null");
}
//Set Previous Data on Postbacks
SetPreviousData();
}
As a summary, the code above gets the previous data stored from the viewstate and set the data stored from it into a DataTable so that we can add a new row based from the value entered from the TextBox.
You will also noticed that we call the method SetPreviousData() at the bottom part of the codes above. Now where is that method? Below are the code blocks for that method:
private void SetPreviousData() {
int rowIndex = 0;
if (ViewState["CurrentTable"] != null) {
DataTable dt = (DataTable)ViewState["CurrentTable"];
if (dt.Rows.Count > 0) {
for (int i = 0; i < dt.Rows.Count; i++) {
TextBox tbName = (TextBox)Repeater1.Items[rowIndex].FindControl("TXTName");
TextBox tbComments = (TextBox)Repeater1.Items[rowIndex].FindControl("TXTComments");
//Disable previous rows
if (i < dt.Rows.Count - 1) {
tbName.Enabled = false;
tbComments.Enabled = false;
}
else {
tbName.Enabled = true;
tbComments.Enabled = true;
}
tbName.Text = dt.Rows[i]["Name"].ToString();
tbComments.Text = dt.Rows[i]["Comments"].ToString();
rowIndex++;
}
}
}
}
Now, since the methods are all set then we can call this at Button Click event of the Post Button.
protected void BTNPost_Click(object sender, EventArgs e) {
AddNewRow();
}
As you can see the code above is very straight forward and self explanatory. Running the code above will give us the following output below:
On initial load:
After adding a new row:


That's it. I hope someone find this post useful!