Alright, I’m going to have a lot of blog posts over the next few days going over my wonderful expereinces learning how to create advanced server controls, and just how hard it is to find good information on the subject. But the problem I ran into today was having Page.FindControl() not work as expected.
Problem
Page.FindControl() can be misleading. A developer without understanding the situation could assume FindControl() will return a control found within that page. This is completely wrong. The reason this does not work is because Page does not have its own FindControl() function. It actually inherits this from Control, because Page inherits control. So FindControl() is really more like a FindChildrenControls(), and it is not recursive.
Example
I have some code that does a Page.FindControl() for a GridView. However, later I move the GridView into an UpdatePanel to add ajax enabled stuff. All of a sudden my Page.FindControl() doesn’t work. The reason? Because my GridView is no longer a direct child of the Page and it is now a child of the UpdatePanel. So instead of being Page -> GridView it is Page -> UpdatePanel -> GridView.
Solution
I found a blog post for a recursive post. Here is the code:
[csharp]
private Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
[/csharp]
thx for that post, it was quite helpful and made me understand the innner workings of asp.net a little better 😀
LikeLike
Thank you sooooooooooooooooo much
LikeLike
You’re welcome 🙂 I haven’t used ASP.NET for almost a year now, but I’m glad my findings still help people out.
LikeLike
Thank you. Thank you. Thank you.
LikeLike
I am kind of a rookie to ASP.Net controls. I created a dynamicPanel Control (custom) for doing partial refreshes with AJAX. I cant find the control on a page using a masterpage and a content panel. What would be the value for the “Control Root”?
LikeLike
Thank you.
LikeLike
This is great!
LikeLike
Thanks so much!
LikeLike
Thank Heavens! I spent a little bit of time on this and was pulling my hair out. Thanks for saving me potential hours!
LikeLike
Thank you very much!!! What a life saver.
LikeLike
Replace Page.FindControl() to NamingContainer.FindControl()
LikeLike
Thank you very much!!!
LikeLike
Yes, many thanks !
LikeLike
Hi Tom. I replaced Page.FindControl() with NamingContainer.FindControl(), but I am getting a
object Reference not set to an instance of an object error.
My code is as follows:
string ctrlStr = String.Empty;
Control c = null;
foreach (string ctl in HttpContext.Current.Request.Form)
{
// handle ImageButton controls …
if (ctl.EndsWith(“.x”) || ctl.EndsWith(“.y”))
{
ctrlStr = ctl.Substring(0, ctl.Length – 2).Replace(“$”, “_”);
//c = page.FindControl(ctrlStr);
c = page.NamingContainer.FindControl(ctrlStr);
}
WHEELS
LikeLike
Hi, i rarely subscribe to all possible web site in the world, but i have donne it with yours just to thanks you.
I regularly got a lot of problem to correctly findcontrol for a lot of situation of control inside another control, and so on…
for now it is so easy with the function you write above
thanks a lot again 🙂
LikeLike
Hi, thanks!
Improved it a bit
private Control FindControlRecursive(string id)
{
Page page = HttpContext.Current.Handler as Page;
return FindControlRecursive(page, id);
}
private Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
Call it like this
Literal debug = (Literal)FindControlRecursive(“debug”);
debug.Text = “asdasd”;
Nice, thanks again
LikeLike
Nice post! My own FindControlRecursive helped me out many times. Especially, when I deal with MasterPages. For example, one of such usage is shown in my post here – http://dotnetfollower.com/wordpress/2010/12/sharepoint-add-onchange-attribute-to-dropdownchoicefield/.
Thank you!
LikeLike
This article is very nice.
Thank you very much.
LikeLike
Sometimes developer must understand where to place this code.
If you’re code in user control, you should use Parent.FindControl.
I found this solution in my application.
LikeLike
Is this still the case?
MS JavaScript used to have that beautifull document.forms[0].inputs[5] syntax that everyone loves so much. Good to see it’s made a comeback in .net
LikeLike
I copied the code above and I had to change from “private” to “protected” in order to use the function. I used it, but it still doesn’t work!!!
LikeLike