Theme support in WPF
Adding theme support in WPF is easy, and your users will love it
An old joke goes like this: "Want to know how to get a million dollars in real estate? First, get a million dollars; then..."
Ever since I first saw WPF, I wanted to give my users the ability to change themes - colors, look and feel, and with WPF, even the way that controls respond to a mouseover. It's really, really easy. But first, you have to have some themes.
Theme resources are just xaml files containing <styles> for all of your controls. As you probably know, you can declare styles in the Dictionary.Resources section of each form (Window, Page, etc.). Or, you can put style declarations in the App.xaml file, and they'll be applied to all of your forms.
But you can also put your styles in a resource dictionary (theme) file, which is just a .xaml file. When you programmatically make it the current ResourceDictionary, the styles for all of your screens change. Give this ability to your users, and they'll enjoy changing their screens' look and feel from time to time.
The easiest way to get them is to download some free themes. There are a bunch of them at http://wpfthemes.codeplex.com/. Download them, extract them to a Themes folder in your WPF project directory, and include them in the project. (You'll have to select Show all files from the icons beside the project name in the Solution Explorer, and you may have to click on the Refresh icon as well)
Fig. 1: Including the downloaded Theme resource files in your project
You'll also have to open the Properties sheet and mark the themes as Resources (Fig. 2)
Fig. 2: Marking your themes as resources
We're almost done. Now, either add a combobox to your MainForm, or add a MenuItem for each theme. The code below assumes you're using a combobox in which you've selected the name of one of your style files. If you instead use MenuItems, include the name of the resource file name that you've chosen in the MenuItem Click event code. Resource files are .xaml files, so be sure to add the extension. And since the .exe file is located in the .bin directory, and on my development machine the resource filea are located a Themes folder two directories above the .bin folder, their names are preceded with "..\..\Themes\".
Listing 2: InteractiveChange event code for your Themes combobox:
private void comboBox1_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
// If you load the theme names into the Items collection of the ComboBox, rather than using a datatable or
// other collection, the SelectedValue looks like this: "System.Windows.Controls.ComboBoxItem: ExpressionDark"
// So, you have to parse the SelectedValue string to get the theme name. Seems a little crude...
string s = comboBox1.SelectedValue.ToString().Substring(comboBox1.SelectedValue.ToString().IndexOf(":") + 2);
using (FileStream fs = new FileStream( @"..\..\Themes\" + s + ".xaml", FileMode.Open))
ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
The effect of picking, for example, ShinyRed, can be seen in Fig. 3:
Fig. 3: Applying a theme
And that's all there is to it.
There are some peculiarities with the Microsoft themes that make them a little problematic for testing. For example, some themes assign White to label text, while others color label text Black. It's pretty challenging to find a background color that makes both look good, and I didn't do so good in that regard in this example. But you get the idea.
I hope you're encouraged to add theme support to your WPF apps. It's easy, and I'll bet that most of your users will love it!
|Copyright(C) Pinter Consulting, 2018||Tel: +1 (650) 464-6924|