East coast technology blog

Post navigation

StyleSheetTheme – the Unsung Hero of .NET 2.0

I had an issue today that was not clearly covered in blogs that I found on the subject, so I thought I would write a little post explaining what the problem is and what my solution was.

My issue was on a .NET 2.0 page. As simply put as possible: Using a Theme was causing my browser-specific css to get ignored.

My Masterpage was using a simple IE-conditional to include css written specifically for IE7 (and another for IE<7). We also had a generic basepage that every page inherits.

For some reason (and I’ll explain why in just a second) my ie7.css file was just not getting recognized by any of my pages. I quickly checked the source of the page and found that the order of css on the page went: ie7.css in the conditional, followed by all my Theme css files located in App_Themes/Themename/css.

Introduction to Themes

In case you are new to .NET 2.0 and Theming, the general idea behind it is that you have a special folder called App_Themes. Inside this folder, you can make subfolders. These folders should be the names of your theme, so if you want a blue theme, the file structure would generally look like ~/App_Themes/Blue, and then images and css directories under that.

Why is this useful? .NET 2.0 includes the ability to set a page directive called “Theme”. At the top of a page, there’s some junk thrown in there by .NET, like MaterPage, Title, etc. You can add to that: “Theme=’Blue'”.

What happens next is that all that css is imported automatically. Presumably as well that css should have a relative path to the images. You can have skin files and all kinds of things in the Theme. The magical part is, if you want, you can also set the Theme programmatically. If this is the case, you could have some kind of Session variable, in theory, that “knows” where on the site you are, if you have different areas, and then set the Theme to the appropriate area. For example a Green area that has article.aspx and news.aspx.

In the Green/Blue example, if you used the same css class names (or even the same css FILE, copied in two different directories) you can literally just swap the image colors and automatically have two completely different looking websites running off of the same exact aspx/cs files.

The best part of Theming this way is that all you have to do in a codebehind is say, literally: “Page.Theme=”Green”;” and you get the Green Theme.

So what was my issue?

The Issue

The Theme css is imported automatically. Anything inside the Theme folder gets grabbed and added to the page in a <link rel=…> tag. This is fine. It’s not what it’s doing, but where. These are added automatically at the END of the head tag, by default. Good by IE conditional statements.

The IE conditional statement is supposed to pull in a stylesheet with extra or different definitions that override the current css in the case of IE. However, with css, the last version of a definition is used by default. So it was like my IE files were not even there.

The Solution

StyleSheetTheme! This is a second kind of theme that differs from the “Page.Theme” version of .NET 2.0’s theme system. (Geez the word Theme is starting to lose all meaning to me at this point… sorry 😦 I didn’t name these things!) A StyleSheetTheme differs from the regular theme in two ways:

1) The way it is added to a page programmatically

2) Where it positions the css on the page

StyleSheetThemes are specifically designed so you can alter the css with other stylesheets. Instead of placing everything last, it places it FIRST. This is incredibly useful for things exactly like browser-specific css files, or small little inline things you may want.

The reason I think so many people ignore this theme type is because of how it is implemented. On an aspx page you can statically declare it similar to the other theme, in the @Page directive, just by saying StyleSheetTheme=”Green”.

Programmatically, though, things are different. There is no Page.StyleSheetTheme. Instead, you have to override a property. That code would look like this:

protected override string StyleSheetTheme

{

get { return “Green”; }

}

This can happen in the basepage, which makes the most sense, honestly. You might notice that this is also static. Using a variable won’t help much, either, since it’s not executing at preInit or onLoad, it’s a separate method. What you CAN use, though, is a Session variable, as long as it’s not null.

Conclusion

This simple solution saved me a LOT of hassle today. I recommend more people check out StyleSheetTheme instead of Theme, since Theme requires hacks in order to get it to work well with alternate css paths.

2 thoughts on “StyleSheetTheme – the Unsung Hero of .NET 2.0”

But I still have some question about StyleSheetTheme.
Could you please help me ?

In my web site, I have several themes in App_theme, and need to use different theme for different user.

I set the page.Theme in override onPreInit event of Basepage, and override the StyleSheetTheme in basepage (below code), too.
public override string StyleSheetTheme
{
get { return Session[“theme_name”].ToString(); }
}

But , when I write Page.StyleSheetTheme= “XXX”, it still throw an exception said “The StyleSheetTheme property cannot be set, please override the property instead.
”

What I want to ask is, if I do not set the StyleSheetTheme in Pages .cs or basepage, will the Page use the theme correctly when I change the Page.Theme?

And for use these themes, must I need to set the StyleSheetTheme when I change the theme?
If yes, how can I do this? I have override it , but still throw exception. Are there any wrong in my code?

I believe in that case you would also need to override the “set” method. Using the code you posted above, I think you would say:

Session[“theme_name”] = “XXX”

Trying to set the StyleSheetTheme will always return that error – the point of this exercise is to find ways to get the Theme to change without explicitly setting it – in our case, using a Session variable.