October 17, 2006
Dynamically add controls to the Repeater controlSome times we have to add dynamic controls to the repeater (or) datagrid columns based on the conditions. For placing the dynamic controls, we need placeholder control in datagrid. You can think of a PlaceHolder control as an empty container to which you can add your controls. ASP.NET will remember the values for your dynamic controls; however, you do have to create the controls both on non-postback and postback calls. Once the controls are created in postback mode, ASP.NET will re-associate the posted data with the dynamic controls and repopulate the data automatically.
This example has a table called Parameters that has the following fields to help you determine how to build the table:
|Prompt||Text to display next to control|
|DataType||Text field with the value 'String' or 'TF' in it (This will let you determine which control to show.)|
You also could add extra fields indicating whether the field was required, a minimum/maximum length, and so forth, but this example is designed to show just the use of the PlaceHolder control.
You then can create a simple form like this one:
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="test.aspx.cs" Inherits="test" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml" >
<form id="form1" runat="server">
<asp:Repeater ID="rptFields" runat="server">
<td><%# Eval("Prompt") %>:</td>
<td><asp:PlaceHolder ID="plControl" runat="server" />
<input type="hidden" id="hdnFieldID" runat="server"
value='<%# Eval("pkParameterID") %>' /></td>
<p align="center"><asp:LinkButton ID="btnSubmit"
The code behind for this page looks like this:
public partial class test : System.Web.UI.Page
protected override void OnInit(EventArgs e)
protected void Page_Load(object sender, EventArgs e)
Database db = new Database("(local)", "test", "sa", "dev1227");
private void AddControls(Database db)
DataTable dt = db.GetDataTableAdhoc("SELECT * FROM Parameters
ORDER BY pkParameterID");
rptFields.DataSource = dt;
void rptFields_ItemDataBound(object sender, RepeaterItemEventArgs e)
if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType
DataRow dr = ((DataRowView)e.Item.DataItem).Row;
PlaceHolder pl = (PlaceHolder)e.Item.FindControl("plControl");
TextBox txt = new TextBox();
txt.ID = "txtField" + dr["pkParameterID"].ToString();
CheckBox chk = new CheckBox();
chk.ID = "chkField" + dr["pkParameterID"].ToString();
As you see in the Page_Load routine, you need to load the dynamic controls every time—not just on the initial load of the page. I create an instance of my Database class, which encapsulates all my database code. Replace this with your favorite data access routine, but the sample uses a DataTable holding the contents of the Parameters table, which is bound against the Repeater control.
The ItemDataBound event does the bulk of the work here. It first determines that you are looking at an ItemTemplate (or AlternatingItemTemplate), and then it grabs the DataRow from the event arguments. This row holds the data type for the parameter, and a switch statement lets you get to the right area to add the right control. In each case, you instantiate a control of the appropriate type (TextBox vs. CheckBox) and then add it to the placeholder control (held in the pl variable). This causes the control to be displayed to the user.
If you wanted to give the control a default value, you'd need to check whether you were in postback mode prior to putting the value into the control or checking the box by default. If you didn't do this check, you'd essentially erase the user's input each time.
In the test page, you can type your data in and then press the Submit button. The Submit button will reload the page, which will show you that the values you typed in are repopulated automatically via the page's view state. This is a handy technique for building dynamic forms, especially those driven from user-configurable data.