Introduction
This article explains how to find controls on any number of levels of Master pages using a single method without typecasting or doing Master.Master
. The concept used here is Dynamic Polymorphism by overriding the FindControls()
method.
Background
There are situations where you have just added nesting to Master pages in your application and some controls have been moved to the super master page. All your FindControl
methods which were called using Page.master
would break, and you would now have to do Page.Master.master
plus the type cast. I have devised a method so that none of the code is affected. Only thing you need to do is add some code to the newly created Master file. I find it useful to have a single method which finds for the control scanning through the hierarchy of master pages above the content page.
Using the code
I have tried to make use of dynamic polymorphism here. As we know, every Page
class or master page class has an inbuilt FindControl
method which finds controls in that page. To have the FindControls
method find controls anywhere in the hierarchy, I have simply done the following.
Let's say we have two levels of nesting:
BaseMasterPage.master
, code-behind BaseMasterPage.master.cs
SubMasterPage.master
, code-behind SubMasterPage.master.cs, master file: BaseMasterPage.master
- MyPage.aspx, code-behind MyPage.aspx.cs, master file:
SubMasterPage.master
Having set up the hierarchy as above, create a super base class called SuperBaseMaster.cs.
public class SuperBaseMaster : MasterPage
{
}
Override the FindControl
method in SuperBaseMaster.cs as shown in the code snippet below. I have also used a recursive method to find the control up to the base master page.
Note: For this to work, all the master pages code-behind classes must derive from a common super base class which is derived from MasterPage
, as shown above
public Control BaseFindControl(string id)
{
return base.FindControl(id);
}
public override Control FindControl(string id)
{
return FindMyControl(id, this);
}
private Control FindMyControl(string id, BaseMasterPage master)
{
if (master == null) return null;
Control ctl = master.BaseFindControl(id);
if (ctl == null)
{
return FindMyControl(id, (BaseMasterPage)master.Master);
}
return ctl;
}
Here in the above code, BaseFindControl
does what the original FindControl
method used to do. Since we have overridden FindControl
, we need some way to get to the original one. Hence this method.
Next, the overridden FindControl
will call our recursive method FindMyControl
.
FindMyControl
will first try to find the control on the current master which is passed as a parameter. If the control is not found, then it calls itself again with the next higher level master (master.Master
), and this goes on till the control is found. If not, a null
is returned in the end.
So far so good.
If you have come this far, then let's see how to call our overridden FindControl
method. For this, let's assume that we want to find a textbox control with the ID "myTextBoxID
". And, this control exists on the BaseMasterPage
. Here is the code for it:
<body> <form id="form1" runat="server">
<div>
<asp:TextBox ID="myTextBoxID" runat="server"></asp:TextBox>
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
</asp:contentplaceholder> </div>
</form></body>
To find this textbox control from our content page in the traditional way, you would do:
SubMasterPage subMaster = (SubMasterPage)this.Page.Master;
BaseMasterPage baseMaster = (BaseMasterPage)subMaster.Master;
TextBox mytextBox = (TextBox)baseMaster.FindControl("myTextBoxID");
And now, using our dynamic method, you would do:
TextBox myTextBox = (TextBox)this.Page.Master.FindControl("myTextBoxID");
That's it. One line. For any level of hierarchy, it will be just one line. And, no typecasting needed (although there are other ways to avoid typecasting, I would not go into the details of that).
The main point here is, this will act as a generic method for the master pages, and you don't have to worry when controls are moved up and down the hierarchy, which happens when the masters are refactored.
Hope this will be useful for those working with refactoring nested master pages. Comments are welcome.