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:
- Building a Web Service in ASP.NET 3.5
- Using Stored Procedures in the Entity Framework with Scalar Return Values
- Get the list of ODBC data source names programatically using C#
- Getting Started with Microsoft Chart Controls for ASP.NET 3.5
- C# Free Component to Generate PDF - Convert HTML to PDF
- Connecting to SQL Server, Oracle, and MySQL with Database or Windows Authentication
Recent comments
- Never seen this issue
3 days 6 hours ago - Error in query.ToList()
3 days 9 hours ago - Thanks
3 days 21 hours ago - Thanks
6 days 19 hours ago - To get the data working,
1 week 2 days ago - If I manually change the
1 week 2 days ago - Handling EDM Relationship Metadata
1 week 2 days ago - About the itextsharp version
1 week 2 days ago - Not sure
1 week 4 days ago - Green traffic bars
2 weeks 2 days ago
Similar
- Fixing Relative Paths in C# ASP.NET When Using Url Rewriting
- GridView ObjectDataSource LINQ Paging and Sorting
- How to Highlight the Day in the ASP.NET Calendar Control with the SelectedDate Property
- Global.asax Events in IIS 6 and IIS 7 for Static Resources
- Create a Windows-style GroupBox in ASP.NET


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