Adding a Merged Dictionary to a Merged Dictionary

14,828

Solution 1

This is an optimization bug, see this link

On the creation of every object in XAML, if a default style is present (i.e. style w/ a key of Type) that style should be applied. As you can imagine there are several performance optimizations to make that (implied) lookup a light weight as possible. One of them is that we don’t look inside Resource Dictionaries unless they are flagged as “containing default Styles”. There is a bug: if all your default styles are nested in merged dictionaries three levels deep (or deeper) the top dictionary does not get flagged so the search skips it. The work around is to put a default Style to something, anything, in the root Dictionary.

So adding a dummy style to the root dictionary fixes this. Example

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Mine;component/Themes/Theme.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <!-- Dummy Style, anything you won't use goes -->
        <Style TargetType="{x:Type Rectangle}" />
    </ResourceDictionary>
</Application.Resources>

Solution 2

Your sample code has a double equal sign in the App.xaml merged resource dictionary source for Palette.Blue.xaml. I'm assuming this is a typo for your example posted here, and not your real problem though.

It can be tricky to figure out how to link all the resources directly in XAML. The easiest way to do it is from the Resources panel in Blend. I created a Silverlight app with resource files named like your example, then opened the project in Blend and very quickly linked them together.

App.xaml

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SilverlightApplication1.App">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Theme.xaml" />
                <!--
                <ResourceDictionary Source="Palette.Blue.xaml"/>
                <ResourceDictionary Source="Template.xaml"/>
                -->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Theme.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Palette.Blue.xaml"/>
        <ResourceDictionary Source="Template.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Template.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="TextBox">
        <Setter Property="Margin" Value="10" />
        <Setter Property="Width" Value="250" />
    </Style>
    <Style x:Key="ReadOnlyTextBoxStyle" TargetType="TextBox">
        <Setter Property="IsReadOnly" Value="True" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Margin" Value="10" />
        <Setter Property="Width" Value="250" />
    </Style>
</ResourceDictionary>

Palette.Blue.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="BlueSolidColorBrush" Color="SkyBlue" />
</ResourceDictionary>

MainPage.xaml

<UserControl x:Class="SilverlightApplication1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot" Background="Honeydew">
        <TextBox Text="Read Only Textbox"
                 Style="{StaticResource ReadOnlyTextBoxStyle}" />
        <TextBox Text="Blue Textbox"
                 Background="{StaticResource BlueSolidColorBrush}" />
        <TextBox Text="Read Only, Blue Textbox"
                 Style="{StaticResource ReadOnlyTextBoxStyle}"
                 Background="{StaticResource BlueSolidColorBrush}" />
    </StackPanel>
</UserControl>

Of course, if you're linking resources from different assemblies it will look different. Actually, in that case, I'd suggest looking into merging your dictionaries in the code behind.

Share:
14,828
The Real Baumann
Author by

The Real Baumann

Shop smart. Shop S-Mart.

Updated on June 06, 2022

Comments

  • The Real Baumann
    The Real Baumann almost 2 years

    I can't seem to be able to add a merged dictionary to a collection of merged dictionaries within XAML.

    Theme.xaml

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Mine;component/Themes/Palette.Blue.xaml"/>
        <ResourceDictionary Source="/Mine;component/Themes/Template.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    

    Application Resources

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Mine;component/Themes/Theme.xaml"/> 
                <!--
                <ResourceDictionary Source=="/Mine;component/Themes/Palette.Blue.xaml"/>
                <ResourceDictionary Source="/Mine;component/Themes/Template.xaml"/>
                -->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
    

    Note: if I put both ResourceDictionaries in the Appication.Resources MergedDictionary (comment out the theme.xaml and uncomment the other two dictionaries) they both load correctly. However, the way our resources are defined, this may mean that quite a few resources will be loaded, and for dynamic loading I'd like to be able to define templates.

  • The Real Baumann
    The Real Baumann almost 14 years
    That was apparently a transcription error (not in the actual file.) I know how to add each resource individually (via code behind or creating a new MergedDictionary) but the issue seems to be something to do with adding a mergedDictionary to a ResourceDictionary either as the source or part of a seperate merged dictionary.
  • Matt Casto
    Matt Casto almost 14 years
    Check the build action of your dictionary xaml files. You might need to change it from the default Page to Resource.
  • dex3703
    dex3703 about 11 years
    I've run into this exact problem in .NET 4 and this solves it.
  • erodewald
    erodewald about 11 years
    For some reason, this does not work for me. Upon starting, it throws an exception (DependencyProperty.UnsetValue is not valid for 'Foreground') which indicates that the resource dictionaries are not getting added. Mine is set up identically to the code above on .NET 4.5.
  • Franck
    Franck about 10 years
    this doesn't not work in VS2010 .net 4.0 this does NOT compile. error Error 7 Property elements cannot be in the middle of an element's content. They must be before or after the content.
  • Joe
    Joe over 4 years
    Would anyone know if this bug is fixed in .NET 4.5 or later? Microsoft Connect has been retired so I can't tell from the link provided.
  • Masius
    Masius over 2 years
    This SO thread explains how OverrideMetadata works