Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Accessing Controls on Nested Master Pages from Content Pages using Dynamic Polymorphism

0.00/5 (No votes)
30 Oct 2007 1  
How to access controls on nested master pages from content pages using dynamic polymorphism without casting to master page classes.

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:

  1. BaseMasterPage.master, code-behind BaseMasterPage.master.cs
  2. SubMasterPage.master, code-behind SubMasterPage.master.cs, master file: BaseMasterPage.master
  3. 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 currentmaster is null, then the control with "id" is not found
    //so return null


    if (master == null) return null;
    //Call the inbuilt base FindControl

    Control ctl = master.BaseFindControl(id);

    if (ctl == null)
    {
        //Call the FindMyControl method recursively

        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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here