Find a control in a TemplateField programmatically
When you add a DetailsView or GridView control to your page, you may need to programmatically access that control in the code behind. You might look at the System.Web.UI.Page object and see it has a FindControl (http://msdn2.microsoft.com/en-us/library/31hxzsdw.aspx) method built in for you. If you thought that you could get ANY control on the page...
You would be wrong.
Unfortunately, this function does not recursively search all controls on the page. Instead, it only searches the immediate child controls of the page (ie: Form, etc.) The problem is that if you have a DetailsView control on the page and want to get at a template field in the control, you have to search the DetailsView control's child controls for this item.
You might try instead to search the Page.Form.Controls collection but again, you have the same problem because the form control collection only contains the direct child controls on the page. In the case below, the only control it contains would be "DetailsView1". Here's what the page looks like with a DetailsView1 control and a TemplateField called "Name":
<body>
<form id="form1" runat="server">
<div>
<asp:DetailsView ID="DetailsView1" runat="server"
AutoGenerateRows="False"
DataSourceID="ObjectDataSource1">
<Fields>
<asp:TemplateField HeaderText="Name" SortExpression="Name">
<ItemTemplate>
<asp:Label ID="lblName" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtName" runat="server" Text='<%# Bind("Name") %>'></asp:TextBox>
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox ID="txtName" runat="server" Text='<%# Bind("Name") %>'></asp:TextBox>
</InsertItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
</div>
</form>
</body>
There are a couple of ways you can still access this control programmatically. First, let's "view source" to see how these controls are named when the page generates them:
<table cellspacing="0" rules="all" border="1" id="Table1" style="border-collapse:collapse;">
<tr>
<td>Name</td>
<td>
<input name="DetailsView1$txtName" type="text" value="My Value 1" id="DetailsView1_txtName" />
</td>
</tr>
</table>
Notice that the page names the "txtName" control as: "DetailsView1$txtName". This follows for multiple rows in the control. The ASP.NET page generation builds the name as follows:
[Parent Container Control Name]$[Child Control Name]
We have to recursively traverse the control tree to look at each control in each container control to find this TextBox. A nice shortcut that isn't well documented is that you can reference the control directly using the FindControl method with this syntax:
TextBox txtName = (TextBox)Page.Form.FindControl("DetailsView1:txtName");But a lot of the time you don't even know the container control and just want the control globally across all controls on the page. In that case, we can use recursion to loop through all elements on the page and find the control by it's ID. Here's a simple method that traverses the Page.Form controls collection and returns the control with the specified ID:
private Control FindControlRecursive(Control ctlRoot, string sControlId)
{ // if this control is the one we are looking for, break from the recursion // and return the control. if (ctlRoot.ID == sControlId) { return ctlRoot;}
// loop the child controls of this parent control and call recursively.foreach (Control ctl in ctlRoot.Controls)
{Control ctlFound = FindControlRecursive(ctl, sControlId);
// if we found the control, return it.if (ctlFound != null)
{ return ctlFound;}
}
// we never found the control so just return null.return null;
}
You would use this method with the following lines of code:
// search for the control by it's ID.Control controlToFind = FindControlRecursive(DetailsView1, "txtName");// make sure something was returned (ie: not null).if (controlToFind != null)
{ // cast the control to a TextBox.TextBox txtNameFound = (TextBox)controlToFind;
// do something with the TextBox control.}
One thing to remember is that recursion can be slow so you only want to use the second method when you cannot use the first. Also, the recursive method should be called with the lowest level Control container parent you have. In other words, calling it on the Page.Form object could/should be slower than calling it on the DetailsView control which has fewer controls to traverse.
Popular Articles
Last viewed:
- Fixing Relative Paths in C# ASP.NET When Using Url Rewriting
- C# Store/Retrieve File in Database Image Field using ODBC
- C# Free Component to Generate PDF - Convert HTML to PDF
- Ajax - Exception has been thrown by the target of an invocation
- Performance benchmarks for LINQ vs. SqlDataReader, DataSet - LINQ Compiled Queries: Part 2
- C# Download File with Progress Bar
Recent comments
- "Windows Client File Set" #Change this How?
21 hours 19 min ago - thanks
4 days 12 hours ago - VPN
1 week 2 days ago - string s = null;
s =
1 week 6 days ago - I am using following
2 weeks 1 day ago - Fantastic
2 weeks 5 days ago - Very Nice
2 weeks 6 days ago - Nice Document
2 weeks 6 days ago - tabela
3 weeks 4 days ago - Good work
4 weeks 1 day ago

Thank you very much
No how would you get the value once the control is found ?
good working
very nices info
thanks
Great! Thanks...
This has been racking my brain for hours!
A nice shortcut that isn't well
A nice shortcut that isn't well documented is that you can reference the control directly using the FindControl method with this syntax:
TextBox txtName = (TextBox)Page.Form.FindControl("DetailsView1:txtName");
Nice. Thanks!
Thanks for writing
Thanks for writing this.
The blog is helpfull...visit also
The blog is helpfull...
Extension
The Same Method with Generic Type and Extension Method
public static T FindControlRecursive(this Control.ControlCollection controls, Control control, string controlName) where T : Control
{
if (control.Name == controlName)
{
T returnControl = control as T;
return returnControl;
}
foreach (Control ctrl in control.Controls)(ctrl, controlName);
{
T findControl = controls.FindControlRecursive
if (findControl != null)
{
return findControl;
}
}
return null;
}
Best Regards
Suleyman Ozturk