While working on the recipe browser application I experienced for the first time, what will be the horror of every developer. I had one huge Styles.xaml file that I generated by letting Expression Blend put all the designed control templates and styles into that file. This works kind of okay when you can design the styles using Expression Blend. But it’s not so much fun anymore when you have to poke around in the file when something is going wrong and the designer doesn’t work anymore.
In this article I’ve put down 5 tips that hopefully helps you to make more effective use of resource dictionaries for your styles and control templates.
Tip 1: Move styles and templates into separate resource dictionaries
It’s tempting to put a control template with the control that you made the template for. This is especially true for templates that you think will only be used for that single instance of the control.
Leaving the control template or style with the control it was designed for, makes it harder for you to reuse the template or style elsewhere in the application. Also, it makes the XAML file harder to read.
In Expression Blend you can choose to create a new control template in a separate XAML file. To do this you need to select the option Resource dictionary and click the New button in the Create style resource dialog.
If you work with Visual Studio 2010, it’s a bit different, you need add a new ResourceDictionary file to the project and create the style or template there.
After you’re done creating the style or template, you need some way to make it available to other components in your application. You can do this by adding it to the MergedResourceDictionaries collection of the App.xaml file. An example of this is shown below.
1: <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
7: <ResourceDictionary Source="Styles.xaml"/>
8: <ResourceDictionary Source="DataTemplates.xaml"/>
This isn’t the only option to link resource dictionaries to the application. A ResourceDictionary also has a MergedResourceDictionaries collection, to which you can add other resource dictionaries. I used this in the recipe browser to create a structure where the Styles.xaml file references the styles, while the DataTemplates.xaml file references data templates used in the application. Both of these resource dictionaries are then included in the App.xaml file to make all the separate resources available in the application.
Tip 2: Keep resources together
This tip looks a bit weird, considering what I’ve said in tip one. However, the contrary is true. For example, if you have a resource dictionary that contains resources related to a DataGrid, I suggest you keep all of the other resources related to the DataGrid there too.
Some controls have a lot of parts, each having its own style and template. This can be very hard to manage when you make separate resource dictionaries for each of the parts. So these are best kept together in one file or two files, depending on the amount of resources.
Another good trick here is what I’ve talked about in tip 1. Create one file, named Styles.xaml for all the control templates and styles and a separate file for the data templates. This doesn’t make the amount of files to manage any less, but it serves as a great guide for people that don’t know the application very well. Styles.xaml is a very recognizable name, so they probably start looking in that file for any styles. However, when they open the file they will see that the actual styles are located elsewhere. The Styles.xaml serves as a sort of roadmap in this case, which can greatly reduce the learning curve.
Tip 3: Shared resource dictionaries
Some resources are used multiple times, for example brushes are often used more than once throughout the application in other templates and styles. Instead of redefining the colors and brushes for control templates and styles, you can place them in a separate resource dictionary and reference that dictionary each time you need those brushes.
Referencing a shared resource dictionary can be done by adding it to the MergedResourceDictionaries collection of the ResourceDictionary that uses the shared resources.
When the time comes that you need to change the color of your user interface, all you need to do is to open up the Brushes.xaml file and change the colors there. This can save quite a bit of time and greatly reduces the chances of you forgetting to change that one highlight on a control.
Tip 4: Performance of resource dictionaries
In the previous tip I showed how you can reuse certain resources by placing them in a separate ResourceDictionary that is than included in other ResourceDictionary files. How cool this may look, there is a cost involved.
Each time a resource dictionary is referenced, the runtime will load that dictionary into a new instance of the ResourceDictionary class. So if your application has 25 ResourceDictionary files that each reference two shared ResourceDictionary files, you will end up with 50 extra instances of the ResourceDictionary class that contain 50 copies of the same resources. This uses up a lot of memory and is unnecessary.
To give you an idea of what a typical application will use in terms of ResourceDictionary instances, I’ve written a small utility that displays how many resource dictionaries are used by the recipe browser.
Having a lot of resource dictionaries makes the application startup time longer as each of the resource dictionaries needs to be loaded and instantiated. To solve the issue you can use so-called cached resource dictionaries.
You can find a blogpost about it here: http://www.wpftutorial.net/MergedDictionaryPerformance.html
Tip 5: Load resource dictionaries only where necessary
There are multiple locations for loading resource dictionaries into your application. Depending on the situation you might want to choose a different location to put your resource dictionaries.
If you place all your resource dictionaries in the App.Resources collection of the application, you will most likely experience slow startup times as more and more resource dictionaries are added. This is because the application has to load all the resource dictionaries from the App.Resources collection during startup.
To make the application boot faster, you can move some of the resource dictionaries away from the App.Resources collection into the Resources collection of screens used throughout the application. This makes the screens a little bit slower to load, but this has much less impact, because you don’t need all resources on a single screen.
Combine this tip with the other tips and you’re application will be much happier 😉