WPF Themes – The Problem
I’m working on a WPF project, and I wanted to add theming capability to it. What I was wanting wasn’t too sophisticated – just the ability to change the colors (although more would be good). I had seen several CodePlex projects dealing with this, so I downloaded a few of them to check them out – specifically, WPF, WPF Themes, and the Silverlight Toolkit.
All of these looked good at first blush. They all had a decent selection of options, all appeared to offer a complete set of control templates, and all had a method for changing the theme at run time. I figured it was just a matter of picking the one that I liked the best (the WPF Themes one seemed like the most complete option) and move on.
I quickly found that all of the examples that I could find, while apparently fine, were all actually unusable in a real application – that is, any application that was more than a single assembly, with no global resources other than the Theme, and didn’t contain any custom controls.
First of all, the method for theme management was essentially the same for all of them – go to Application.Current.Resources.MergedDictionaries and empty that collection (assuming that the only thing in that collection is the Resource Dictionary for the “current” theme), and then add the Resource Dictionary for the “new” theme. All well and good…but, what if my application has other things in that collection? They are just lost.
Next, there was no consistency in the way that the themes defined colors and brushes. For instance, I wanted to have a panel in a UserControl be the same color as the face of a button. What I would like to do is reference the same brush as the Button template – that way, when the theme changed, the color of my panel would change. However, each theme named the brush used for the button background color something completely different. I originally hoped that it would just be a simple matter of normalizing the names, but I quickly discovered that the internal structure of the themes was so inconsistent that this just wasn’t practical.
And lastly, the scheme was not at all extensible. Since the control templates were defined internal to the theme itself, if I added a new custom control, I needed to add a template to everything theme – even if the only difference was the way the control was colored. Furthermore, if that control is defined in a different Assembly than the themes, there was no way for it to participate in the theme.
In the next couple of posts, I’m going to discuss how I resolved these issues and built my own theming system.