Monday, January 22, 2007

Referencing a Master Page from a User Control

UPDATE: It turns out this works fine for debugging, but once you go to publish it doesn't work at all (if you check the Allow Updateable box). It looks like the Reference Directive is being ignored when compiling the code behind file so it can't find the class "ASP.nameofmymasterpage_master". I'll update again if I find a solution. Very discouraging.

UPDATE 2: see workarounds below

I ran into a situation where I needed to access a custom property of a master page from within a user control. Were I dealing with a regular page, the MasterType directive would have worked fine, but this doesn't work for user controls.

I started by figuring out the name of the type of my custom master page by mousing over a line like "Page.Master" in one of my aspxs that contained a MasterType directive. This told me that the type of the master page is something like "ASP.nameofmymasterpage_master". The parent class for this is the class in the master page cs file, usually something like "nameofmymasterpage".

I then tried casting "Page.Master" to "ASP.nameofmymasterpage_master" in the cs file for my user control, but the compiler complained that it didn't know about this type. To make it aware, you have add the seldom used Reference directive to the ascx file. Something like "<%@ Reference VirtualPath="~/nameofmymasterpage.master" %>". Then the type "ASP.nameofmymasterpage_master" is available so the line with the cast can compile and everything works.

In summary, put this in the ascx:
<%@ Reference VirtualPath="~/nameofmymasterpage.master" %>

So that you can do this in the ascx.cs:
string thingIwant = (Page.Master as ASP.nameofmymasterpage_master).CustomProperty;

WORKAROUNDS:
1. Just use Web Application Projects which I should be doing anyway, but I haven't yet gotten the time to update all the sites we currently have
2. Define an interface in your App_Code folder with all the operations you need exposed from your master page. In your master page cs file, mark the class as implementing your interface. Then in your ascx, just cast Page.Master to your interface type and go to town. You don't need the Reference directive at all. Not as simple as it should be, but it works.

2 comments:

SLAP HAPPY said...

Use Web Application Projects and you can do this all day :)

Eniac said...

i know this is an old post by google found it for me and i need to say that using an interface to expose custom master page properties is a genius idea. it solved my problem right away.