Setting StyleSheetTheme globally - impossible?

Onion Blog

Syndication

One common request from developers when they learn about themes in ASP.NET 2.0 is for a way to set the theme globally at runtime. Unfortunately there is no simple way to do this, although there are ways, as several people have posted in the past. The one technique that I have favored is to add a handler for the PreRequestHandlerExecute event in global.asax and register a new PreInit handler for each page, setting the theme in the new handler. This technique can be applied to a site without changing anything else in the site, including the base class of each page (which is another common approach).
 
Here's an example of overriding the handler in global.asax and setting the theme dynamically based on a Profile property called "theme":
 
// In global.asax
void Application_PreRequestHandlerExecute(object src, EventArgs e)
{
  Page p = this.Context.Handler as Page;
  if (p != null)
  {
    p.PreInit += new EventHandler(page_PreInit);
  }
}
void page_PreInit(object sender, EventArgs e)
{
  Page p = this.Context.Handler as Page;
  if (p != null)
  {
    p.Theme = (string)Context.Profile["theme"];
  }
}
 
I was demonstrating this technique at a conference talk recently, and someone asked if you could do the same thing with StyleSheetTheme (which is basically the same thing as Theme, except that it applies the skin properties of controls before the declarative attributes of a control on a page are applied). To my surprise, it failed with an exception stating that you must override the StyleSheetTheme property of the page class to change it (unlike the Theme property which you can just set). So apparently the only way to set the StyleSheetTheme globally is to override the virtual property:
 
public override String StyleSheetTheme
{
  get { return Profile.theme; }
}
 
This is fine if you have access to the page to override the property, but it means that you can't use the same global injection technique that you can for the Theme attribute. The closest you can get is to create a common base class for all the pages in your site and override the StyleSheetTheme property. You then must go through all of your pages and have them inherit from this new base class instead of Page (this includes both code behind file classes and direct pages without code behind). Bleh. I'll stick with "Theme" and keep the relatively clean handler injection…
 
 

Posted Aug 02 2006, 08:00 AM by fritz-onion
Filed under:

Comments

Christopher Steen wrote Link Listing - August 2, 2006
on 08-02-2006 8:40 PM

My
ASP.NET 2.0 Tips, Tricks, Recipes and Gotchas "Highlights Page" [Via:
ScottGu ]
Sending...
adam strait wrote re: Setting StyleSheetTheme globally - impossible?
on 06-25-2008 11:56 PM
I have found a way around this that does not require using a common base class. This works if you can define the new theme within a posted form. Its a bit ugly, because it involves manually extracting the control value from the viewstate, but it works:

private string sOverrideTheme = "defaultTheme";

public override string StyleSheetTheme
{
get {
if (Request.Form.ToString().IndexOf("ThemeSwitch") != -1)
{
int start = (Request.Form.ToString().IndexOf("ThemeSwitch")) + 12;
int end = Request.Form.ToString().IndexOf("&", start);
int length = end - start;
sOverrideTheme = Request.Form.ToString().Substring(start, length);
}


return sOverrideTheme;
}
}
Apti wrote re: Setting StyleSheetTheme globally - impossible?
on 08-03-2008 8:52 AM

Very interesting article and provided a solution to my problem, however when i did a Server.Transfer i lost the theme as the Application_PreRequestHandlerExecute event is not fired on the transferred to page.  Was you aware of this and could you offer any solutions?

Add a Comment

(required)  
(optional)
(required)  
Remember Me?