With the recent public release of the Silverlight Toolkit one of the interesting features has to be the Theming. There has been a number of cool posts about theming and Jonas has a great post about how to leverage existing themes that have already be designed.
Theming in WPF is a great feature and something that was rather disappointingly not part or the Beta 2 Release, Nikhil came up with a good work around, however it was still rather developer focused in its implementation and not too designer friendly. My current project requires the ability for the controls to be themed for different implementations on startup and also the ability of a generic skin to be applied if certain parameters have been supplied. The new Themes provides all the functionality that I required to achieve the expectations of the client. However, it was not as simple as I had hoped. Once you know about a couple of little quirks then it all falls into place, so I thought that I would put together a simple project that highlights the gotchas and includes the 3 different ways of leveraging theming in your Silverlight application.
Before we dive in a little bit of background information on the project. The sample application is a Social Bookmarking control that has become common place on web pages and blogs. My goal is to have a large social bookmarking theme and a small social bookmarking theme that can be applied to the control. The requirement has come from the designer who has already built the 2 styles and templates for the social bookmarking control and needs them wired up. The Social bookmark control is a lookless control, in that it derives from Control and has declared TemplateParts for the UI elements that it needs in its tree. It also lives in its own project called Controls. The MyThemes project uses the Social bookmarker control and is where the themes will be declared. The final project is a web project to host the MyThemes Xap.
The first task is to remove all the x:Key properties from the App.xaml file, but only for the control that uses the style, the other styles that are referenced by the control templates in the App.xaml can stay as they are.
The next task is to create a new folder in the MyThemes project and to hold our custom themes, in this case I created 2 Silverlight User Controls called Large and Small. Remove the code behind for the User Controls as we won’t be needing them. Open up the Xaml and remove all the code, as we need to use ResourceDictionary for our themes. The final part here is to change the properties on the Large and Small Xaml files to be of type Content. It would be great to see a Silverlight Resource Dictionary template in VS which would do these manual steps. The file properties caused me the most trouble in this whole process which I will pick up later on in the post.
Move over to the App.Xaml and locate the style for the large social bookmarker control and cut and paste this into the large theme Xaml file we created in the previous step, do the same for the small. You will almost certainly have to fix references to assemblies so go and track them down and fix them up.
Taking a quick look back we have created our new themes for the application and reused the styles that were in our original App.xaml file that the designer built. Our next step is to wire up the Social bookmarker control to the themes. Now this is important, as we have set the properties on our theme files to be Content we have to load the themes up using Xaml in a declarative manner. So head over to MyTheme project and add a reference to the Theming assembly then open up Page.xaml so that we can wire up the control to the right theme. The Implicit Style Manager provides all the goo that we need for associating the control to the theme and we do this by calling the Resource Dictionary Uri and the ApplyMode dependency properties.
In my sample you can see that I am applying the Small theme to the control. Ok so we are done not too tricky hit F5 and make sure that you can see the control. My own experiences here is that the error messages that you get back are not particularly helpful, most of the time it will say that the Xaml line where you declared your Implicit Style Manager is broken, what it actually means to say is that you have a problem with the Xaml declared within the file you are referencing. Now this could be the case but it also could be that you have not changed the file to have the correct build properties. What I found out here is that if you are going down the declarative Xaml approach the file properties need to be set too Content, if you are going to load up the themes from code then you need to change the build properties of the file to a resource.
So let go ahead and add a button so that we hit the button and load up the Social bookmarker control with the large theme. In order to do this we need to write some code in the Page.xaml.cs file and more importantly we have to change the build properties on the LargeTheme Resource dictionary as we plan on applying the theme using code. So first go and change the build properties on the LargeTheme.xaml file to be Resources. Now jump back to the code behind for the Page.xaml.cs and here we need to wire up the theme to the Social bookmarker control. There are a couple of steps that we need to do here; Remove the control from the visual tree; new up another Social bookmarker and add this back into the tree; finally we need to tell the Implicit Style Manager which theme we want and then apply the theme to the Social bookmarker control.
Hit F5 and you will now be able to view the Control with the Small theme applied and then hit the button and the Social bookmarker control will change the theme and load up with the large theme applied. Cool.
The final part of the puzzle is to create a new Silverlight Class library to hold a compiled version of the themes, this is another option for how to use theming. Once you have created the project remove all the generated .cs files and copy over the Large theme from the previous project. Double check to make sure that the file still has the resource build properties selected and then build the project. We can now jump back to the Page.xaml.cs file and change the URI to point to our new baked in theme. Sweet hit F5.
So there are 3 different ways in which to use the new theming in your Silverlight application depending on what your needs are and how far you want to go with decoupling your themes from you main Silverlight application and controls library. You can grab the source from my skydrive.