Access Controls Contained in a MasterPage through a Content Page

Introduction

MasterPages are a great feature that's new to the .NET 2.0 framework. They simplify the process of applying a look and feel across multiple pages in your ASP.NET application. Before these came about making a change that would apply to all your pages was quite a task as you had to go around to each page and make the change manually. Not only was it inefficient but there was always the possibility that you would miss a page. Now you can make the change in one file and the change will automatically be reflected in all your content pages.

There are times when you want to be able to customize a portion of your masterpage from your content page. There is actually a couple ways to accomplish this task. Follow me in this article as I show you how.

The "FindControl" method

Every control in asp.net exposes a public method called "FindControl." The purpose of this method is to find a child control that isn't exposed by a property. The way it accomplishes this is by taking a string as input which is the ID of the control you want to locate and if the control is found return that control as an instance of the Control class. You will then need to cast this reference to the type of control you're looking for. If the method does not find a control with the specified ID then a null reference (in VB nothing) will be returned.

How can you put this to good use in your content pages? Let's say for example you have a label placed on your master page. You decide you want to modify the Text property of this label. First thing you would do is call the master's FindControl method passing the ID of the label control and casting the return value to a Label. It's best to check for a null reference before doing anything with the label. That way if it wasn't found you can handle the situation yourself instead of an exception being thrown. Below is an example of how to do this.

// The FindControl method will pass back an instance of Control class

Control masterPageControl = Page.Master.FindControl("MyLabelID");

 

// Cast the control reference to a Label

Label masterPageLabel = masterPageControl as Label;

 

// Check whether the control was found by testing the reference

if (masterPageLabel != null)

{

masterPageLabel.Text = "Some new text";

}

else

{

// Write some code here to handle when the label wasn't found

}

As you can see, once you have a reference to the label you can modify its properties just as if the control was contained in the content page. This method can be applied to any type of control contained in your master page or really any control as every control exposes the FindControl method.

Creating a public property to access controls

The FindControl method is nice and simple and if you only need to access a control from one page it's a good way to go. However, if you're going to be accessing the same control on multiple pages you might want to consider this next method which involves exposing a public property from your masterpage. This allows you to contain the logic in one spot and achieves a strongly-typed reference to the control. It also gives you the ability to limit modifications to a certain property of a control rather than letting the content page have a complete reference to the control.

Going back to our previous example if you only wanted to let content pages modify the text of the label then you could expose that property through your own public property. That way you don't have to turn over the whole control to the content page. Below is an example of a property to expose the text of the label.

public string MyLabelText

{

get

{

return MyLabel.Text;

}

set

{

MyLabel.Text = value;

}

}

If on the other hand you wanted to expose the whole control then you would implement the property in this way.

public Label MyLabel

{

get

{

return MyLabel;

}

}

Notice I made this property read-only as the content pages will not need to create a new label in this instance.

At this point we've only implemented half of this method. If you were to add a property to your masterpage in this manner, go to a content page's code-behind and try to access it by calling Page.Master.MyLabelText it would not work. The reason is this. By default the Master property of the Page returns an instance of the MasterPage type and not an instance of your specific masterpage type. This property doesn't know what masterpage is used until you tell it. This takes us to the other step of this method.

If you go to the source view of your content page at the top you'll of course see the page directive which begins like this "<%@ Page". Below that you can add a variety of directives which allow you to accomplish different things. We're interested in the "MasterType" directive. This lets you specify which masterpage the content page uses for purposes of your code. There's actually two ways to use this directive. The most common method you will use is to specify the VirtualPath for your masterpage. An example of this implementation would look like this.

<%@ MasterType VirtualPath="MasterPageVirtualPath" %>

The other option offered by this directive allows you to specify the type of the master page. Use this option when you have built a masterpage in another assembly or a class which is contained in the app_code directory.

<%@ MasterType TypeName="MasterPageTypeName" %>

You will need to include one of these implementations of the MasterType directive in every content page that will access your property.

Conclusion

That's all there is to it. Now you know two ways to access controls in your masterpage and the pros and cons so that you may decide which is the best method for you to implement.

Allan    5/8/2008 12:42 PM

Great article, I am looking forward to trying this out tomorrow morning.

Allan    5/9/2008 9:47 AM

I am getting the following error when trying to compile using the code to expose my control property: "Object reference not set to an instance of an object."

 

The error is thrown on the following line: MyLabel.Text = value;

.NET Advisor    5/9/2008 9:59 AM

Allan,

 

Do you in fact have a label control on your masterpage whose ID is "MyLabel"? The exception indicates that the masterpage can't find it.

 

Rob

Allan    5/9/2008 10:08 AM

Site1.Master:

 

<asp:HyperLink ID="HyperLink1" NavigateUrl="~/WebForm1.aspx" runat="server">HyperLink</asp:HyperLink>

 

 

Site1.Master.cs:

 

public string HyperLink1Text

{

get

{

return HyperLink1.Text;

}

set

{

HyperLink1.Text = value;

}

}

 

The null error is thrown on: HyperLink1.Text = value;

 

 

Allan    5/9/2008 11:10 AM

It turns out the error is thrown due to code in the ContentPage Page_Load event:

 

 

1 using System;

2 using System.Data;

3 using System.Configuration;

4 using System.Collections;

5 using System.Web;

6 using System.Web.Security;

7 using System.Web.UI;

8 using System.Web.UI.WebControls;

9 using System.Web.UI.WebControls.WebParts;

10 using System.Web.UI.HtmlControls;

11

12 namespace MasterPageAndCSSDemo

13 {

14 public partial class WebForm1 : System.Web.UI.Page

15 {

16 protected void Page_Load(object sender, EventArgs e)

17 {

18 HyperLink ctrl = (HyperLink)Master.FindControl("HyperLink1");

19 ctrl.Enabled = false;

20

21 Site1 obj = new Site1();

22 obj.HyperLink1Text = "TEST";

23

24 }

25 }

26 }

 

When the parser reaches line 22, the parser goes to the master page code behind before the actual HyperLink1 control is created.

 

So, what is the correct way to expose a control on the master page?

 

Allan    5/9/2008 11:14 AM

So, I guess I am correctly exposing the HyperLink1 control. But, it is only functional after the master page code behind is processed.

.NET Advisor    5/9/2008 12:22 PM

Hey Allan,

 

Looks like you've actually combined both methods which is ok but unnecessary.

 

However, the reason you're getting an exception at line 22 is because you're trying to set the value on a new instance of your masterpage instead of the instance that your code is tied to. Change line 21 and 22 to this:

 

Master.HyperLink1Text = "TEST";

 

Don't forget to declare the MasterType in your sourceview also.

 

Another thing, you can tell the code is able to find the hyperlink in the masterpage from lines 18 and 19. If 18 had not returned an instance of a hyperlink you would've received an error on line 19 where you tried to set the value of the Enabled property.

 

Rob

Allan    5/12/2008 7:37 AM

> Looks like you've actually combined both methods which is ok but unnecessary.

 

Just testing all of my options.

 

>However, the reason you're getting an exception at line 22 is because you're trying to set the value on a new instance of your masterpage instead of the instance that your code is tied to. Change line 21 and 22 to this:

 

>Master.HyperLink1Text = "TEST";

 

>Don't forget to declare the MasterType in your sourceview also.

 

It works now. Thank you for your time, I really appreciate it.

New Comment

  
  
  
  
Email Print