(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .
        Login with Facebook

Merged Resource Dictionaries in Silverlight

(6 votes)
Emil Stoychev
>
Emil Stoychev
Joined Oct 15, 2007
Articles:   23
Comments:   98
More Articles
14 comments   /   posted on Mar 23, 2009
Categories:   General

This article is compatible with the latest version of Silverlight.

Merged Resource Dictionaries provide a way to define and split resources into separate files. By locating application resources in external file we can then reuse them between applications. This feature can be helpful in custom control development, but not only.

In Silverlight 2 resources cannot be factored into separate files and that leads to large App.xaml file holding application-wide shared resources. The same problem exists while developing custom controls. All default style keys must be specified in Themes/Generic.xaml which again leads to very large file.

Merged Resources Dictionaries are a great solution for these problems – you are free to split style definitions and other resources into manageable pieces, making it easy to localize and revise.

Download Source Code

Usage

Ok, enough theory. Let’s see how to make use of MergedDictionaries.

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="..." />
            <ResourceDictionary Source="..." />
            <ResourceDictionary Source="..." />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

MergedDictionaries contain a collection of ResourceDictionary objects with specified Source attribute. The Source points to the file where the ResourceDictionary is defined.

ResourceDictionary is defined in external XAML file (in the same or different assembly) with root element ResourceDictionary like this:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <SolidColorBrush x:Key="TitleBrush" Color="DarkViolet" />
    <SolidColorBrush x:Key="ContentBrush" Color="Black" />
</ResourceDictionary>

There are several ways to use a merged resource dictionary which are indicated by the URI format that you will use. You can either include your resource .xaml file in the project as Resource or as Content.

If you include it as a Resource you don’t need to copy the resource file to the output directory. You can use it by specifying the URI in the following format:

Source=”/<assembly name>;component/<resource file name>”

You can also use a Content build action. Then the URI format is the following:

Source=”<resource file name>”

To use a resource defined in external assembly you just need a reference to the DLL and then you just have to set the Source path including the external assembly name.

All the 3 cases of using merged resource dictionaries we discuss, are included in the attached sample project and are illustrated by the following example:

 <UserControl x:Class="MergedResourceDictionaries.MainPage"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <UserControl.Resources>
         <ResourceDictionary>
             <ResourceDictionary.MergedDictionaries>
                 <ResourceDictionary Source="BrushResources.xaml" />
                 <ResourceDictionary Source="/ExternalResources;component/DataResources.xaml" />
                 <ResourceDictionary Source="/MergedResourceDictionaries;component/TextResources.xaml" />
              </ResourceDictionary.MergedDictionaries>
              <Style x:Key="TitleStyle" TargetType="TextBlock">
                  <Setter Property="FontSize" Value="18" />
                  <Setter Property="Foreground" Value="{StaticResource TitleBrush}" />
              </Style>
             <Style x:Key="ContentStyle" TargetType="TextBlock">
                 <Setter Property="Foreground" Value="{StaticResource ContentBrush}" />
              </Style>
         </ResourceDictionary>
     </UserControl.Resources>
     <StackPanel>
         <TextBlock Style="{StaticResource TitleStyle}" Text="Merged Resource Dictionaries" />
         <TextBlock Style="{StaticResource ContentStyle}" Text="A great way to manage and reuse resources" />
         <TextBlock Text="{StaticResource MRD}" />
         <ListBox>
             <TextBlock Text="{StaticResource Silverlight3}"/>
             <TextBlock Text="{StaticResource WPF}"/>
         </ListBox>
     </StackPanel>
 </UserControl>

On line 7 we use a resource included as a Content in the project which contains two SolidColorBrushes – TitleBrush and ContentBrush used on line 13 and 16.

On line 8 we use a resource included as a Resource in the same project.

On line 9 we use a resource included as a Resource in external assembly referenced by our project.

Performance

Christian Moser from WPFTutorial.net talks about merged resource dictionaries performance in one of his tutorials - Improve the performance of merged ResourceDictionaries. There he states:

“Each time a control references a ResourceDictionary XAML creates a new instance of it. So if you have a custom control library with 30 controls in it and each control references a common dictionary you create 30 identical resource dictionaries!”

That’s absolutely true. He created a SharedResourceDictionary that helps you get rid of this problem. Read his tutorial to learn more about that.

Read more

Merged Resource Dictionaries on MSDN

Improve the performance of merged ResourceDictionaries


Subscribe

Comments

  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by Pavel on Mar 24, 2009 00:14
    Including resources as Resource does not work when I try to use it in an external assembly. May work in WPF~21~3f I kept the ResourceDictionary as a Page and everything worked fine.~3cbr /~3e
  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by Ryan lin on Mar 24, 2009 01:33
    hi guys what about resources in difference file dictionary?
    for example move main.xaml to a subfold whatever,
    that just throw a exception.and there is no documentation there for a reference,please tell me how to resolve
  • emil

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by emil on Mar 24, 2009 04:27
    @Pavel, did you look at the source code? You can see that I included DataResources.xaml as a Resource in external assembly (ExternalResources) and then use it without any problems in MergedResourceDictionaries assembly. Take a look at it and let me know whether there is something not clear.

    @Ryan, there is no problem to do that. Here is what you need to do:
    1 <ResourceDictionary Source="MergedResourceDictionaries;component/SubFolder/SubBrushResources.xaml" /> 
    2 <ResourceDictionary Source="/SubFolder/SubBrushResources.xaml" /> 

    If you include your resources as a Resource (build action) you should you use the snippet on the first line where: MergedResourceDictionaries is the assembly name
    SubFolder is the name of the sub folder where you put your resources
    SubBrushResources.xaml is the name of your resource dictionary file

    If you include your resources as a Content (build action) you should use the snippet on the second line where:
    SubFolder is the name of the sub folder where you put your resources
    SubBrushResources.xaml is the name of your resource dictionary file

    Does this make sense to you?

    Hope that helps!
  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by smalle on Mar 31, 2009 09:19
    Hi Emil,

    I am trying to do the following:
    I have a resource project ResDict with 2 files: styles.xaml and assets.xaml.
    styles.xaml needs the info in  assets.xaml (brushes).
    styles.xaml is used in another SL project MainPrj.

    following your indications, I was able to use the styles in styles.xaml in the MainPrj, when styles.xaml doesn't use the brushes in assets.xaml.

    how can I use the definition in assets.xaml within styles.xaml in my MainPrj?

    ADDITIONAL INFO:

    Build action for style.xaml and assets.xaml is Resource.

    Code in style.xaml:

     <ResourceDictionary.MergedDictionaries>

        <ResourceDictionary Source="ResDict;component/assets.xaml"/> 

    </ResourceDictionary.MergedDictionaries> 

    Code in App.xaml in PrjMain

     <Application.Resources> 

        <ResourceDictionary Source="ResDict;component/styles.xaml" /> 

    </Application.Resources> 

    Thank you very much in advance for your help!
  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by sidhu on Aug 12, 2009 01:41
    I downloaded your source code and tried to run it. I got runtime errors in InitializeComponent(xmlParserException with message  Attribute ExternalResources;component/DataResources.xaml value is out of range. [Line: 8 Position: 44]) for both

     <ResourceDictionary Source="ExternalResources;component/DataResources.xaml" />
    <ResourceDictionary Source="MergedResourceDictionaries;component/TextResources.xaml" /> 

    It worked fine if i comment both these lines. Is there any settings I need to change? or copy any resource files?


  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by sidhu on Aug 12, 2009 01:42
    I downloaded your source code and tried to run it. I got runtime errors in InitializeComponent(xmlParserException with message  Attribute ExternalResources;component/DataResources.xaml value is out of range. [Line: 8 Position: 44]) for both

     <ResourceDictionary Source="ExternalResources;component/DataResources.xaml" />
    <ResourceDictionary Source="MergedResourceDictionaries;component/TextResources.xaml" /> 

    It worked fine if i comment both these lines. Is there any settings I need to change? or copy any resource files?


  • emil

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by emil on Aug 12, 2009 10:13
    Hi sidhu,

    the problem is that the code was compiled with Silverlight 3 Beta. For Silverlight 3 RTW you need to put a slash '/' at the beginning of the source path. Like this:
     <ResourceDictionary Source="/ExternalResources;component/DataResources.xaml" />
    <ResourceDictionary Source="/MergedResourceDictionaries;component/TextResources.xaml" />


    Hope that helps!
  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by Assaf S. on Aug 24, 2009 20:54
    I've came across another issue -

    When the external assembly name contains dots (for example AssemblyNamePart1.Part2), an error is thrown.
    After removing the dots (e.g. AssemblyNamePart1_Part2), everything worked fine.

    Assaf
  • emil

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by emil on Aug 25, 2009 09:30
    Thank you Assaf, it is useful to know that!
  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by Merlinox on Oct 13, 2009 11:50

    I've tried to use it on a generic.xaml but it doesn't work.

    My struct is like this:

    • SilverlightClassLibrary1
      • Themes
        • generic.xaml
      • CT
        • MyTabControl.xaml
      • MyTabControl.cs

    MyTabControl is my custom control that inherit ItemsControl. MyTabControl.xaml contains all ControlTemplate(s) and properties definition.

    I tried to insert in generic.xaml:

    <ResourceDictionary.MergedDictionaries> 
        <ResourceDictionary Source="/local;/CT/MyTabControl.xaml" /> 
    </ResourceDictionary.MergedDictionaries> 

    But it doesn't work, why? Thanks.

     

  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by Aaron on Feb 22, 2010 21:59

    Emil,

    Thanks for the post. Consider the following scenario: You have a custom control library (called: "SomeOtherLibrary") with one customized UserControl in it, called "CustomControl." CustomControl merges a ResourceDictionary from an assembly called "External_ResourceLibraries," like so:

    <UserControl.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="/External_ResourceLibraries;component/BasicStylesDictionary.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </UserControl.Resources>

    Let's say that you look at that customized UserControl in Blend and experience no problems. Now let's say you try to use that customized UserControl in your web application like this:

    <SomeOtherLibrary:CustomControl />

    Should the UserControl that creates an instance of "CustomControl" have to have a reference to the External_ResourceLibraries assembly in order to run? I have an application that works in this way, and need to know if this is the appropriate way of using MergedDictionaries in custom UserControl libraries. This process seems redundant, inefficient, and illogical. Can you help me understand why this custom UserControl can't be used in another UserControl's assembly without explicit references to the External_ResourceLibraries that it attempts to merge together?

    Thanks,

    - Aaron

  • -_-

    http://welcome-re.ru/


    posted by JerryMirro on Jun 05, 2010 10:05

    Your article is really very interesting. This is the information, I’ve been looking for… Thanks

    <a href="http://welcome-re.ru/karelia.aspx" title="Недвижимость в Карелии">Недвижимость в Карелии</a>

  • -_-

    RE: Merged Resource Dictionaries in Silverlight 3


    posted by Rob263 on Sep 20, 2010 19:36
    This works for me in Silverlight 3, but when I try it in Silverlight 4 it crashes - has anyone else tried it?
  • lnikolov

    RE: Merged Resource Dictionaries in Silverlight


    posted by lnikolov on Mar 01, 2011 11:03
    The article has been updated to the latest version of Silverlight and Visual Studio.

Add Comment

Login to comment:
  *      *       
Login with Facebook