Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referencing a Parent's ResourceDictionary in a UserControl

I have a library of WPF UserControls, and a ResourceDictionary that is shared within the library.

All the UserControls in this library appear only within a single 'shell' parent control, which is really just a container for a collection of smaller controls. I'm able to access the ResourceDictionary from my shell control as expected when I add the following XAML

<Control.Resources>
    <ResourceDictionary Source="MyResources.xaml" />
</Control.Resources>

However I can't access the ResourceDictionary from child controls that sit inside the 'shell' control.

I was under the impression that WPF should check locally for resources, and then traverse upwards until appropriate resources are found?

Instead I'm getting

Cannot find resource named '{BoolInverterConverter}'. 
Resource names are case sensitive.  Error at    
    object 'System.Windows.Data.Binding' in markup file...

Obviously I can (and am) referencing the ResourceDictionary in my child controls; but each and every control now needs to reference this dictionary and I believed that this was not necessary.

Any ideas, am I doing something strange or is my expectation of behaviour incorrect?

like image 760
Kirk Broadhurst Avatar asked Jan 31 '11 03:01

Kirk Broadhurst


1 Answers

What's going on is described here, though the documentation's a little opaque. If you add a ResourceDictionary to an element'sResources property without specifying a key, WPF expects that you're merging in resource dictionaries, and it populates the dictionary with the contents of the dictionaries in its MergedDictionaries property. It ignores the actual contents of the ResourceDictionary with no key.

So what you want to do is this:

<Control.Resources>
   <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="MyResources.xaml"/>
      </ResourceDictionary.MergedDictionaries>
   </ResourceDictionary>
</Control.Resources>

Edit:

A working example:

MainWindow.xaml:

<Window x:Class="MergedDictionariesDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MergedDictionariesDemo="clr-namespace:MergedDictionariesDemo" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <MergedDictionariesDemo:UserControl1 />
    </Grid>
</Window>

Dictionary1.xaml:

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

UserControl1.xaml:

<UserControl x:Class="MergedDictionariesDemo.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Border Margin="10" BorderBrush="Navy" BorderThickness="1" CornerRadius="10">
        <TextBlock Margin="10"
                   Background="{DynamicResource UCBrush}">
            The background of this is set by the resource UCBrush.
        </TextBlock>

    </Border>
</UserControl>
like image 93
Robert Rossney Avatar answered Oct 21 '22 06:10

Robert Rossney