FindControl and Master Pages
Continuing with my earlier post on enums where I proved people wrong, I decided to prove another MVP wrong. Once again, for those who are already in the know, they can skip to Example 2 below.
FindControl Basics
First, a primer on FindControl, taken from the MSDN help:
Searches the current naming container for a server control with the specified
idparameter.
Example: The following example defines a Button1_Click event handler. When invoked, this handler uses the FindControl method to locate a control with an ID property of TextBox2 on the containing page. If the control is found, its parent is determined using the Parent property, and the parent control’s ID is written to the page. If TextBox2 is not found, "Control Not Found" is written to the page.
private void Button1_Click(object sender, EventArgs MyEventArgs)
{
// Find control on page.
Control myControl1 = FindControl("TextBox2");
if (myControl1 != null)
{
// Get control's parent.
Control myControl2 = myControl1.Parent;
Response.Write("Parent of the text box is: " + myControl2.ID);
}
else
{
Response.Write("Control not found");
}
}
Searching Master Page Content Using FindControl
You could build a recursive FindControl method that searches master pages and content pages internally by looping through each control and checking the ID—but then you’d also need to build one for the offset-overloaded version. Sounds like too much work, and I guess Microsoft thought so too, since it was never designed this way.
Example 2: If you wanted to search the master page for a control, you could do the following:
this.Master.FindControl("ControlID");
This will find any control in the master page that happens to have the ID "ControlID". This control could be a sub-control of another control.
What’s going on here? Well, to understand, I downloaded the famous Reflector and searched Microsoft’s framework for this. The relevant snippet:
protected virtual Control FindControl(string id, int pathOffset)
{
string str;
this.EnsureChildControls();
if (!this.flags[0x80])
{
Control namingContainer = this.NamingContainer;
if (namingContainer != null)
{
return namingContainer.FindControl(id, pathOffset);
}
}
// ... (more implementation)
}
The key takeaway is the recursion happening here. Thus, we don’t need to worry about it ourselves.
But there’s a problem: This only searches the master page. How do we get to the content page?
Example 3: If you wanted to search for a control in the content page, assuming our Content PlaceHolder has an ID named "Content", you could do either of these:
this.Master.FindControl("Content$ControlID");
OR
this.Master.FindControl("Content:ControlID");
There you go—now you can find any control (nested or otherwise) on any content page!