Site Settings, Apply Theme, Apply, Lather, Rinse, Repeat
Applying themes to WSS sites is sometimes like giving birth to a duck-billed platypus on a snowy day in the middle of springtime (can't wait to see the Google search referrals from that statement). I've blogged a little about this before so ignore my rant if you've heard this song already. If all you want to do is select Site Settings | Apply Theme then you're golden. If, however, you're a developer and you're trying to test your custom theme out you need to be aware of a few things.
First, just copying a new THEMES.CSS file into your theme directory in the 60 hive and hitting F5 in your browser isn't going to do Jack. The theme is cached and worse yet, it's part of the site and lives in a virtual directory. In other words, there's no physical place it resides so when you get it served up to you in your browser, you're getting a cached version that's actually coming out of the ASAPI filter that SharePoint is controlling and serving the page through. Open a site in FrontPage and you'll see a _themes directory in the navigation tree but this physically doesn't exist. Look at the source code for a page and you'll see something like this:
<link rel="stylesheet" type="text/css" id="onetidThemeCSS" href="/sites/sitename/_themes/mytheme/mytheme1011-109.css">
(note the name of the them varies based on language, etc.). There is no _themes/mytheme directory physical directory yet you can enter that url and up pops the mytheme1011-109.css file. Again, all the magic of the ISAPI filter at work.
Second, as a developer, it's a PITA to go to Site Settings, Apply Theme to Site, Apply, lather, rinse, repeat. Not only that, you can't simply re-apply the same theme to your site. You have to apply a different theme to the site, THEN apply your custom theme to see the results. This is 600 or so clicks for any change you make to your theme. Needless to say, theme development is like any SharePoint development. Painful and slow.
Okay, a couple of tricks to do to make this less cumbersome and hopefully will make your theme development a little easier on your grey matter. First, get your CSS editor installed on the server. I personally use TopStyle as I can visualize things in the editor, it reformats my output in a nice way (after you've been screwing around with all kinds of styles your CSS file gets a little messy) and it's a pretty slick product overall. Second, it's handy to create a web part to (somewhat) automate the process. Clicking through and going onto the Site Settings page over and over again can drive you to going postal.
Let's create a super-simple web part with the Web Part Template starter in Visual Studio. Add a control (a button or hyperlink will do) to the web part and create a Click event for it. In the click event what you want to do is:
- Get the SPWeb object for the site
- Apply the default theme to the site
- Apply your own theme
- Redirect to the current page
So how do we do this? Simple:
protected
override void CreateChildControls(){
btnApplyTheme = new Button();
btnApplyTheme.Text = "Apply Theme";
btnApplyTheme.Click += new EventHandler(btnApplyTheme_Click);
}
private
void btnApplyTheme_Click(object sender, EventArgs e){
SPWeb web = SPControl.GetContextWeb(this.Context);
web.ApplyTheme("none");
web.ApplyTheme("MyTheme");
this.Context.Response.Redirect(web.Url.ToString());
}
The secret here is to call the ApplyTheme method twice. First with a parameter of "none" which will set it to the default, then with the string for your theme (whatever the name of the folder is in your THEMES directory). This will flush the page enough to reapply it, otherwise just calling it with your own theme won't work.
Okay, install this web part onto your site (the default page will do fine) and open it in the browser. Open up the THEMES.CSS file in your favorite CSS editor and start editing. Save then click your button on your Web Part. Voila. The theme is applied with one click (almost).
There's one problem with this. While it does work, you still need to hit F5 to refresh the page fully and see your changes. Why? Because information is still cached and you need to flush it. I have tried everything to try to do this in code but can't. Mainly because its a client side thing, but also you can't process the ASP.NET control's event AND call say an "onclick" JavaScript (like location.reload(true)) at the same time. At least I can't find a way to do this and I've tried things like setting the HttpResponse to expire, flushing the Cache with SetNoStore(), etc. Nothing seems to work but at least this is a two-click solution rather than 6.
If anyone has a solution to the refresh problem, please feel free to email me or (preferably) post it in the comments. Also if you do theme development (Shane?) maybe you have some tips to share on how you do it. Hopefully this helps you with your theme creation.