无法找到资源"themes.xxx.xaml"运行时错误 - WPF另一个程序集中的自定义组件

4

我试图在我的WPF项目中使用我在一个类库程序集中创建的自定义控件。然而,当我启动应用程序时,我不断地收到"无法定位到资源 'themes/rcttextbox.xaml'" 的运行时错误。

在我的自定义控件库 "SoftwareThemeDesigner" 中,我在 "Themes" 文件夹中有以下的 Generic.xaml 代码:

<!-- 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>

/Themes/RctTextBox.xaml是一个包含<Style>和ContentTemplate的资源字典,这是在Visual Studio中创建"Custom Control"文件时的默认设置。

在我的"WPF应用程序(SoftwareThemeDesignTester)"中,引用了我的"软件主题设计师(SoftwareThemeDesigner)"库,在App.xaml文件中,我有以下代码:

<!-- 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>

我尝试过的方法:

  1. 将所有资源字典的构建操作从“Page”更改为“Resource”
  2. 在Generic.xaml文件中为每个资源字典添加/SoftwareThemeDesinger;component/前缀
  3. 将RctTextBox.xaml代码移至Generic.xaml,并删除资源字典文件以及对其的引用(见下文)。
<!-- 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>

这个方法是有效的,但是无法使用单独的资源字典,而且在“Themes”文件夹中定义所有内容可能不可行。

请问有人能提供建议吗?我已经花费数小时在谷歌上寻找解决方案,但都没有成功。感觉好像少了点什么。

提前感谢!

根据@ Bizhan的答案更新的代码

<!-- 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>

这个回答解决了你的问题吗?如何使用在ResourceDictionary中定义的样式 - Bizhan
请阅读以下链接:https://learn.microsoft.com/zh-cn/dotnet/framework/wpf/app-development/pack-uris-in-wpf将WPF中的包URI翻译成中文。 - Bizhan
@Bizhan 谢谢您的快速回复。我也尝试过应用程序打包,但它并没有起作用。 - The Don
样式在库本身中起作用吗? - Bizhan
是的,这些样式在库本身中确实起作用。我将修改此问题以简化和尝试其他操作。 - The Don
1个回答

4
似乎编译器找不到资源,因为要么没有编译它,要么引用了错误的URI。
首先,请确保每个资源字典的生成操作(Build Action)为Page,并且自定义工具(Custom Tool)为MSBuild:Compile。
然后,请确保在两个项目中均使用其完整的Pack URI设置每个ResourceDictionary的Source。
<ResourceDictionary Source="pack://application:,,,/SoftwareThemeDesinger;component/Themes/Generic.xaml" />

注意1:您可以安全地省略pack://application:,,,部分。
注意2:如果资源字典仅在本地程序集中使用,则包含程序集名称是可选的。但是,如果您正在引用另一个程序集中的资源字典,则在源和目标项目中包含程序集名称是必需的。我没有找到清晰的解释,但我认为这种行为是由于BAML阅读器将字典合并在一起,因此最终它试图在相对路径中查找资源(在这种情况下是SoftwareThemeDesinger项目根目录)。
您可以在此处阅读有关Pack URI的更多信息。

太好了。如果你要在外部程序集中使用它,那么你必须在源程序集本身中引用它。我将使用你的答案更新我的问题代码。非常感谢你的帮助,@Bizhan。 - The Don

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接