Chengting
Chengting

Reputation: 355

StaticResource not found when using WPF control in another assembly

I made a WPF UserControl and want to reference it in another project. But even though the UserControl is usable in its own assembly, when referenced in the other project, StaticResource not found problem occurs.

My UserControl looks like this:

<UserControl x:Class="DiagramDesigner.VacSymGrmV"
             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" 
             xmlns:local="clr-namespace:DiagramDesigner"
             xmlns:s="clr-namespace:DiagramDesigner"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <local:DesignerCanvas Focusable="true"  x:Name="vacgrm"                         
                            Background="{StaticResource WindowBackgroundBrush}"
                            Margin="10" FocusVisualStyle="{x:Null}"
                            ContextMenu="{StaticResource DesignerItemContextMenu}"/>
    </Grid>
</UserControl>

The problematic point is: {Static Resource WindowBackgroundBrush}, which is a resource defined in a XAML file:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
   <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
   <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#000" />
   <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
</ResourceDictionary>

This assembly is an EXE and in the design window of the UserControl, I can see it is correctly displayed, and it compiles and runs.

But when I want to use the UserControl in another WPF application, like in the following code, this application throws an exception on startup, claiming that WindowBackgroundBrush is not found:

<Window x:Class="XVacSysComp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vac="clr-namespace:DiagramDesigner;assembly=VacSymDgm"
        xmlns:local="clr-namespace:XVacSysComp;assembly=XVacSysComp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <vac:VacSymGrmV>
  
        </vac:VacSymGrmV>
    </Grid>
</Window>

The VacSymGrmV is the UserControl an´nd not surprisingly, the UserControlis not correctly displayed in the design window.

The exception says:

Exception: 'WindowBackgroundBrush' is not found, and pay attention to uppder/lower case ...

Is this some problem related to the location of static resource, when using it in another assembly?

Upvotes: 0

Views: 2336

Answers (2)

thatguy
thatguy

Reputation: 22089

The exception tells you the exact problem, the WindowBackgroundBrush is not found.

'WindowBackgroundBrush' is not found, and pay attention to uppder/lower case ...

The resource is defined in a resource dictionary that you merged anywhere in the containing assembly (EXE), e.g. the application resources. If you use the user control there, the static resource can be resolved.

However, if you use the user control from a different application, how would that application access resources from any other assembly automatically? Even if your user control would be located in the assemly (EXE) of your original application, just referencing it from a different application or library will not bootstrap the other WPF application or magically add the referenced resources from there to the executing assembly.

The solution is simple, merge the corresponding resource dictionary to the application resource dictionary of the other application or a different resource dictionary in scope for resolution of the resource. In case of shared resources, consider creating a dedicated assembly that can be reference by different projects.

<ResourceDictionary>
   <!-- ...other resources. -->
   <ResourceDictionary.MergedDictionaries>
      <!-- ...other resource dictionaries. -->
      <ResourceDictionary Source="pack://application:,,,/MySharedAssembly;component/MySharedResourceDictionary.xaml" />
   </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

For more information about referencing a resource dictionary from a referenced assembly and the source syntax used in the example, have a look at the pack URI documentation.

Depending on your scenario, you could also merge and supply the resources with your user control, but I guess for the resource in question this does not apply, as it is an application background.

Upvotes: 3

Lana
Lana

Reputation: 1046

You should import your resource dictionary to your UserControl

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

Upvotes: 2

Related Questions