Resource organization

Sep 2, 2008 at 7:53 AM

I have downloaded the source code of CAL, it's great, thanks for your excellent work. Now i decide to develop the project by Prsim, but i met a problem :

1. How to organize the ResourceDictionary?

As usual, i define basic style and resource in some separated .xamls, and merged them into App.Resource.  then the control use BaseOn={StaticResource xxx} to overide the basic resource.
Now i did the same thing, i define a SolidColorBrush <SolidColorBrush x:Key="BackgroundBrush" Color="Black"/> in App.Resource, and use Background={StaticResource BackgroundBrush} in a separated module to use it.
But it failed, i received a exception, i thought maybe the StaticResourceExpression did not find the resource, So i wrote a custom ResourceExpression, it inherited from StaticResourceExtension.

        public override object ProvideValue(IServiceProvider serviceProvider)
            IProvideValueTarget target = null;

            if (serviceProvider != null)
                target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

            if (target == null)
                throw new InvalidOperationException("MarkupExtension doesn't have property parser context available");

            DependencyObject targetObject = target.TargetObject as DependencyObject;

            if (targetObject == null)
                throw new InvalidOperationException("SmartResourceExtension can only be used for DependencyProperty");

            object resourceReferenceExpression = null;

            resourceReferenceExpression = Application.Current.TryFindResource(base.ResourceKey);                                 //Failed
            resourceReferenceExpression = Application.Current.MainWindow.TryFindResource(base.ResourceKey)            //Succeed

I define the SolidColorBrush in App.Resource, use Application.Current.TryFindResource(base.ResourceKey), failed.
Then i move it to Shell.Resource, and use Application.Current.MainWindow.TryFindResource(base.ResourceKey), it succeed.

This confused me, why can't find it in App.Resource. From your sample, all the resource were in the same control.Resource, i want to make the resource reused, how can i do it?
Is it a limitation or something wrong i made, plz indicate, thanks.

2. the second question is our UI designer use Blend to design the UI, but Blend usually show an error, The resource "BackgroundBrush" could not be resolved, although the application goes well.
this is the same as the problem above, if i put the resource in UserControl.Resource, it resolved.

i see,  modules will be separated, maybe developed by different developers, but how to recongize the resource making them reused and goes well in Blend?

Thanks for any suggestion.

Sep 2, 2008 at 12:12 PM


I believe you could leave your original code, just ensure a couple of things:

1. Put all your resources in a centralized assembly.
2. Projects should be built, and deployed, in a central location.


This will allow you to link your resources from any of your Xaml UI's.
    <!--<ResourceDictionary Source="/[Qualified.AssemblyName];component/[ResourceDictionary.xaml]"/>-->
    <ResourceDictionary Source="/CentralizedResources;component/MyResources.xaml"/>

3. With this declaration ClientApplication, ModuleA and ModuleB should be able to access resources from your centralized resource assembly.

4. Now your designers can collaborate by focusing on the CentralizedResources project to produce resources. Here is an article that might gove you ideas about how to better approach your resource organization.

5. Developers should use resources from the CentralizedResources assembly. Designers should not have knowledge of custom controls, but can have knowledge of base controls, i.e. TextBox, Rectangle, ListView, StackPanel, etc. The CentralizedResources assembly should not have any dependencies outside what is in the "xaml" and "xaml/presentation" uris.

Hope this helps,

Andres Olivares

Sep 3, 2008 at 4:54 AM

Thanks for your reply. I got it and follow your steps, everything goes well.

But one resource maybe meraged twice.

Example :



Both ModuleA and ModuleB have ListBox and want to use the ListBoxStyle which in CentralizedResource(e.g. {StaticResource key} or BaseOn={StaticResource key} ).  So i have to merge ListBoxResource into two Xaml UIs.
Or i have to define ModuleAResource and ModuleBResource in CentralizedResources, and the modules link their own resource.
Both are not perfect.   :-(

The question i metioned when i merged into App.Resource, i cannot find it. It's my mistake.
I move 
  Bootstrapper bootstrapper = new Bootstrapper();
from the constructor of App to OnStartup(), it's Ok.

So maybe this question is nothing abt Prism, but i stll wanna see the best solution to organize resource.
If i merge all the ResourceDictionary into App.Resource, and all modules can use StaticResource to reference the resource. Only in VisualDesigner or Blend it shows an error, The resource "" could not be resolved.

Shall i drop this idea and donot use Share resource, define one ResourceDictionary for each UI Xaml.
Or in ListBoxResource, define x:Key as x:Key="{x:Type ListBox}" instead of a detailed name.

looking forward to your reply.
Thank a lot.


Sep 3, 2008 at 3:34 PM
Edited Oct 9, 2008 at 11:43 AM


I know what you mean about putting the merged resource declaration in the App.Resources for all. I would avoid this because you do not if know other modules would use these resources.

You are correct; this is not a Prism thing but it is extremely important when considering the designer/developer workflow within WPF development. So let's get a useful solution in here to get things moving - try the following:

1. Add the following assembly attribute to your AssemblyInfo.cs file to your module:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
2. Add a folder name Themes in your module project
3. Create a ResourceDictionary class in the Themes folder and name it generic.xaml
4. Add a reference to your resource and its component in the generic.xaml merged dictionaries collection:
    <ResourceDictionary Source="/[Qualified.AssemblyName];component/[ResourceDictionary.xaml]"/>
    <ResourceDictionary Source="/[Qualified.AssemblyName];component/[ResourceDictionary.xaml]"/>


This will tell the WPF theming mechanism that you have resource dictionary location(s) within your assembly. When using your resources, VS design time might complain about this, but it is quite fine, it will be resolved at runtime.

Hope this helps,

Andres Olivares