views:

417

answers:

3

I have the following code in my ASPX side:

<%@ Page Language="C#" MasterPageFile="~/masterpages/standard.Master" .... %>
<%@ MasterType VirtualPath="~/masterpages/standard.Master" %>

I use the VirtualPath to access properties in my MasterPage. So far, so good.

However, now I have to change masterpages programatically. I know that to change a master page, I have to do on the page_init:

Page.MasterPageFile = "~/masterpages/myNewMasterPage.Master";

But I have no idea, of how to change the VirtualPath.

A: 

Did some digging and found this on the ASP.NET Forums:

To change the MasterType dynamically , you should create a base masterpage class and let every masterPage to inherit from it.

Then you can use that base MasterPage type as a MasterType for your page.

see "Strong Typing for Dynamic Master Pages" section in this link.

Regards,

Anas Ghanem

Seems like a fairly reasonable approach so long as you can live with doing some casting.

Source


If you want to save some time and avoid having to do the casting on every call you could define a field in your base MasterPage type called 'CurrentMaster' or something to that effect and then use a conditional on the current MasterPage file that also sets the 'CurrentMaster' with the appropriate type.

MasterPage CurrentMaster;
if (Page.MasterPageFile == "Master1") {
  CurrentMaster = (Master1Type)Page.MasterPage;
} 
else {
  CurrentMaster = (Master2Type)Page.MasterPage;
}

Source

Nathan Taylor
+2  A: 

I assume you're using MasterType because you need some property (which you would also need if you changed to another master), let's say you are currently using Master.MyButton, move this into a base class and use that type in your @MasterType declaration:

public class MasterBase : MasterPage
{
  public Button MyButton;
}

public class standard : MasterBase
{
}

Now in your page, your MasterType declaration looks like:

<%@ MasterType TypeName="MyNameSpace.MasterBase" %>

Now when you change your virtual path, it doesn't matter, you're accessing properties in the base, same for both master pages.

Nick Craver
+2  A: 

To put it shortly, you can't do that.

You see, the "MasterType" directory provides type information, which is used by the compiler at compile time.

When you write something like Page.MasterPage.btn1.Text = "abcd", then the compiler needs to know how to handle that "btn1" part. What is it? Is it a field? A property? A method? A nested class? Or maybe it doesn't exist at all?

To answer these questions, the compiler needs to know the type of the Page.MasterPage expression. And that is exactly what you provide with the "MasterType" directive.

The VirtualPath attribute basically says "go compile that other file first, and the result of its compilation will be the type of this page's Master property". That's how compiler knows.

From all the above, one can draw a conclusion: not only is it impossible to change type of some property at run time, it also doesn't make any sense - the code has already been compiled, you don't need any compile-time information anymore!

So the next question that arises is: why did you want to do this in the first place?

If you just want to use different properties that are declared in different master pages, the you can take Nick Craver and Nathan Taylor's advice and declare a base class that would have all those fields/properties and have all your master pages inherit from that base class, and then have your MasterType directive specify that base class via TypeName attribute.

However, I would only go this way if both master pages are similar in logic, only different in design. That is to say, one page should not have any properties that the other doesn't. Otherwise, it just isn't right to have two subsets of properties/methods/fields in one class (which will be base class) when only one of those subsets is used at any time. And it isn't right to create a common base for two classes when there isn't really a common base there. Aka "bad design". In this case, you should probably rethink your initial design.

If your purpose is some other - please explain, and I will try to come up with some solutions for you.

Good luck with that.

  • Fyodor
Fyodor Soikin
Althoght you have given a nice answer it wasn't the solution. But since it is very usefull for further visitors, I'm going to mark it as Userfull. :)
Marco
It isn't a solution, because there is none. :-) And in my answer I make an attempt to carefully explain why.
Fyodor Soikin