The Don
The Don

Reputation: 353

"Cannot locate Resource "themes.xxx.xaml"" runtime error - WPF Custom Components in Another Assembly

I am trying to use custom controls that I created in one class library assembly in my WPF project. However, I keep getting the runtime error "Cannot locate resource 'themes/rcttextbox.xaml'" when I launch my application.

In my custom control library, "SoftwareThemeDesigner", I have the following Generic.xaml code in my "Themes" folder:

<!-- Original Generic.xaml file in "Themes" folder -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Themes/RctTextBox.xaml" />
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

The /Themes/RctTextBox.xaml is a resource dictionary with a <Style> that has a ContentTemplate, as per the default "Custom Control" file when creating one in Visual Studio.

In my "SoftwareThemeDesignTester" WPF application that references my "SoftwareThemeDesigner" library, in the App.xaml file, I have the following code:

<!-- WPF App's App.xaml file -->
<Application x:Class="SoftwareThemeDesignerTester.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/SoftwareThemeDesigner;component/Themes/Generic.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

What I've tried:

  1. Changing all the build actions of every resource dictionary from "Page" to "Resource"
  2. Adding the /SoftwareThemeDesinger;component/ prefix to each resource dictionary in the Generic.xaml file
  3. Moved the RctTextBox.xaml code to Generic.xaml and removed both the resource dictionary file and the reference to it (See Below).
<!-- Modified Generic.xaml file after removing references to other resource dictionaries -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style TargetType="{x:Type local:RctTextBox}"
           BasedOn="{StaticResource {x:Type TextBox}}>
        <!-- RctTextBox Style details placed here -->
    </Style>


</ResourceDictionary>

This has worked, but it's strange that I can't use a separate resource dictionary, and it may not be practical to have to define everything in the generic.xaml file in the "Themes" folder.

Can any of you please advise? I've spend hours googling a solution and none have worked. I feel like I'm missing something.

Thanks in advance!

Updated Code based on @Bizhan's answer

<!-- Generic.xaml file in "Themes" folder -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/SoftwareThemeDesigner;component/Themes/RctTextBox.xaml" />
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>
<!-- WPF App's App.xaml file -->
<Application x:Class="SoftwareThemeDesignerTester.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/SoftwareThemeDesigner;component/Themes/Generic.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

Upvotes: 4

Views: 4213

Answers (1)

Bizhan
Bizhan

Reputation: 17085

It seems that the compiler cannot find the resource because either it's not compiled or it is referenced with a wrong URI.

First, make sure each resource dictionary has Build Action = Page and Custom Tool = MSBuild:Compile

Then, make sure Source of each ResourceDictionary is set with its full Pack URI in both projects:

<ResourceDictionary Source="pack://application:,,,/SoftwareThemeDesinger;component/Themes/Generic.xaml" />

Note 1: You can safely omit pack://application:,,, part.

Note 2: If a resource dictionary is only used in the local assembly then including the assembly name is optional. But If you are referencing a resource dictionary in another assembly it's mandatory to include the assembly name in source and target projects. I haven't found a clear explanation to this, but I think this behaviour is due to BAML reader merging the dictionaries together so ultimately it's trying to find the resource in the relative path (which in this case is SoftwareThemeDesinger project root)

You can read more about Pack URI here

Upvotes: 5

Related Questions