21

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.

apaderno
  • 28,547
  • 16
  • 75
  • 90
The Real Baumann
  • 1,941
  • 1
  • 14
  • 20
  • is that the full code of the theme.xaml? because i think you only need to start and end it with ResourceDictionary tag to make it work – dnr3 Aug 06 '10 at 01:34
  • No, it's actually in a merged dictionary already. It just doesn't seem to inherit. – The Real Baumann Aug 07 '10 at 22:59

3 Answers3

35

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>
InSync
  • 4,851
  • 4
  • 8
  • 30
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • I've run into this exact problem in .NET 4 and this solves it. – dex3703 Feb 28 '13 at 18:16
  • 4
    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. – erodewald May 06 '13 at 18:58
  • 1
    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.` – Franck May 09 '14 at 12:16
  • 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. – Joe Dec 26 '19 at 15:02
1

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.

Matt Casto
  • 2,150
  • 1
  • 22
  • 32
  • 1
    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. – The Real Baumann Aug 12 '10 at 17:53
  • Check the build action of your dictionary xaml files. You might need to change it from the default Page to Resource. – Matt Casto Aug 12 '10 at 19:56
0

If this is happening on one of your own controls I've found that another solution is setting the DefaultStyleKey property to null:

DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(null));

I have no idea why this works, but it seems to!

Grokys
  • 16,228
  • 14
  • 69
  • 101
  • This [SO thread](https://stackoverflow.com/a/19569389/1450491) explains how OverrideMetadata works – Masius Jan 10 '22 at 12:19