Best Practices: How to handle shared resources in a modular application?

Coordinator
Dec 23, 2008 at 5:41 PM

Note: The examples are based on version 1.0 Milestone 1.

The Test Suite reference implementation defines a few control styles to meet the Microsoft Windows User Experience Interaction Guidelines. I have defined some of the “Recommended sizing and spacing” rules found in the page “Layout”. I would like to apply these default settings to all WPF views in all modules.
 
My requirements for shared resources are:

  • UI Designers must be able to read them at design time (e.g. Cider, Expression Blend).
  • The same resources must not be loaded multiple times. Just once for all modules.
  • Code-behind in the Xaml views should be avoided to retrieve the shared resources.

The approach I’m using in version 1.0 Milestone 1 is simple. I have included the shared resource file with the property MergedDictionaries into every single WPF view.

Example: Message.Demo / Views / DemoView.xaml

<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Jbe.TestSuite.Infrastructure.Interface;Component/Resources/ControlResources.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

The main disadvantage of this approach is that the resources are loaded for every single view. This might require extensive memory usage if you put a lot of resources in the shared resource dictionary or you have many views. The MSDN article “Control Authoring Overview” shows an alternative approach in the chapter “Defining and Using Shared Resources for Your Control”. They introduce a static class called SharedDictionaryManager which is responsible that a specific resource file gets loaded just once. If the resource file is already loaded then it returns the cached ResourceDictionary object. However, this approach needs you to write code-behind to merge the shared dictionary with the resource dictionary of your WPF view.

Do you have a better idea how to define and use shared resources?

Dec 27, 2008 at 2:54 PM
Hi,

I use different approaches for design and run time. I use both Blend and Cider extensively and found this to work pretty nicely.

My scenario is I have a common (infrastructure) dll that contains resource dictionaries that all modules share for styling their components. Each module should also be able to have its own resource dictionaries if necessary. I want this to not only work at run-time, but also at design-time.

For design-time resource recognition and loading, I found this approach to work very well:


For run-time resource recognition and loading, I found this approach to work very well:


There is a section at the bottom entitled "Manage a Collection of Resource Dictionaries in Code and Merge them at the Element Level". This approach loads the resource dictionaries once and allows each component to reference that instance. The only issue here would be teaching the designer to add the resource dictionary references as needed.

Hope this can help.
Coordinator
Feb 9, 2009 at 7:45 AM

Hello hummus!

Many thanks for sharing your approach for using shared resources. I came up with a slightly different approach to overcome these issues.
I have introduced the static ResourceService class in the Composite Extensions Library 1.0 Milestone 2. This class provides an attached property to define shared resource dictionaries.

Example: LogViewDemo.xaml

<UserControl x:Class="Jbe.TestSuite.LogViewer.Demo.Views.LogDemoView"

...      
cae
:ResourceService.MergeSharedDictionaries="/Jbe.TestSuite.Infrastructure.Interface;Component/Resources/ControlResources.xaml">

This works fine with the Visual Studio 2008 WPF Designer (Cider) but I haven’t tested it with Expression Blend so far.

Jul 22, 2009 at 5:27 AM
Edited Jul 22, 2009 at 5:38 AM

Hi,

I'm trying to use your approach, but it doesn't seem to work in Blend. What's really strange is that when I attach a debugger to the Blend process I can see that the relevant code is being executed, and the resource dictionary is being added to the object's Resources.MergedDictionaries property. But afterwards the designer still can't find the resources. Any idea what's going on?

Is it possible that Blend is overwriting the MergedDictionaries with something else? Resources from App.xaml perhaps?

Works like a charm in Visual Studio though.