查找资源字典的设计时错误 - 项目之间不一致
Design-time Error finding the Resource Dictionary - Inconsistent between projects
TLDR;
在 运行 时正确地以 VS2015 样式新引用外部 ResourceDictionary
文件,但在设计时不正确。给出了什么?
在工作中,我们有一个 WinForms 产品,其中包含 许多 个 WinForms 屏幕,其中一名开发人员正在积极添加新屏幕,还有一些 WPF 屏幕,我正在添加新屏幕。注意到现有 WPF 屏幕中有很多重复 code/styling,我创建了一个项目来容纳它 - 供所有 existing/future WPF 屏幕引用。
项目: WpfHelper
- 平台目标:任何CPU
- 目标框架:.NET Framework 4.6
WpfHelper.dll
部署到 ...\Trunk\Project\Externals
...\Trunk\Utilities\WpfHelper\WpfHelper\Resources\GlobalResources.xaml
- 构建操作:页面
- 包含通用样式的 ResourceDictionary
我在六个项目中引用了...\Trunk\Project\Externals\WpfHelper.dll
,将以下代码添加到它们的每个资源文件中:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfHelper;Component/Resources/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
所有屏幕都位于 ...\Trunk\Project\Plugins
。
╔══════════╦═════════════════╦═════════════════╦══════════════════╦════════════════════════════════════════════════╗
║ ║ Resource Works? ║ Platform Target ║ Target Framework ║ Reference File Path ║
╠══════════╬═════════════════╬═════════════════╬══════════════════╬════════════════════════════════════════════════╣
║ Project1 ║ Succeeded ║ Any CPU ║ .NET 4.6 ║ ...\Project1\Project1\Resources\Resources.xaml ║
║ Project2 ║ Succeeded ║ x86 ║ .NET 4.6 ║ ...\Project2\Project2\Resources\Resources.xaml ║
║ Project3 ║ Succeeded ║ Any CPU ║ .NET 4.6 ║ ...\Project3\Project3\Resources\Resources.xaml ║
║ Project4 ║ Failed ║ x86 ║ .NET 4.6 ║ ...\Project4\Project4\Resources\Resources.xaml ║
║ Project5 ║ Failed ║ x86 ║ .NET 4.6 ║ ...\Project5\Project5\Resources\Resources.xaml ║
║ Project6 ║ Failed ║ Any CPU ║ .NET 4.6 ║ ...\Project6\Project6\Resources\Resources.xaml ║
╚══════════╩═════════════════╩═════════════════╩══════════════════╩════════════════════════════════════════════════╝
最近更改
最近我将 Visual Studios 2013 升级到 2015。大约在同一时间,另一个屏幕开发人员将所有现有屏幕项目的目标框架从 .NET Framework 3.5/4.0 升级到 .NET Framework 4.6。
成功项目
- 我在 最近更改 之前引用了
WpfHelper.dll
。
- 样式在设计时和 运行 时正确应用。
失败的项目
- 我在 最近更改 之后引用了
WpfHelper.dll
。
- 样式仅在 运行 次正确应用。
- 在设计时,抛出错误:
An error occurred while finding the resource dictionary "pack://application,,,/WpfHelper;component/Resources/GlobalResources.xaml".
- 使用本地
Resources.xaml
的地方,抛出后续错误:
Value cannot be null.
Parameter name: item
我试过的:
阅读大量文章和问答后:
- Design Time WPF XAML Resource Dictionaries
- How to load a ResourceDictionary at Design Time in WPF
- Error finding resource dictionary in separate assembly
- Problems loading merged resource dictionaries in .NET 4.0
- Pack URIs in Windows Presentation Foundation
- VS2013: An error occurred while finding the resource dictionary
- An error occurred while finding the resource dictionary
- Error finding merged resource dictionary in another assembly
- Trouble referencing a Resource Dictionary that contains a Merged Dictionary
- WPF VS2013: An error occurred while finding the resource dictionary
- App runs normally but has “errors” during design time: “does not exist in namespace” and “an error occured when finding the resource dictionary”
- Resource Dictionary as Linked File
我尝试了以下所有方法均无济于事:
- 将项目平台目标更改为 "Any CPU"
- 更改项目目标框架 from/to .NET Framework 4.6
- 确保所有 Resource.xaml 文件具有相同的生成操作(页面)等
检查了每个项目的 AssemblyInfo.cs
文件。失败的项目包括(我删除了)以下内容:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
手动清除 AppsData 中的临时文件夹,清理并重建项目。
- 重新打开项目。
- 重新启动。
- 右键单击从工作项目中复制的
WpfHelper.dll
引用并粘贴到失败项目的引用中。
- 将
WpfHelper.Resources.GlobalResources.xaml
作为链接文件添加到失败的项目中。
- 唠叨每个同事。
- 为
GlobalResources.xaml
中使用的子词典添加了完整包 URI。
- Killed the designer 并重建项目。
我没有想法并且迷失在研究中。我有 templated 一种可行的解决方案,并将其用于创建新屏幕 - 创建在设计时成功显示的新屏幕。这与这些预先存在的屏幕有关。如何让失败的项目在设计时正确显示样式资源?
我已经找到了解决这个问题的方法,实施起来不费吹灰之力。
首先为资源字典添加一个代码隐藏文件,GlobalResources.xaml.cs:
namespace YourNamespaceHere
{
partial class GlobalResources : ResourceDictionary
{
public GlobalResources()
{
InitializeComponent();
}
}
}
然后将x:Class属性设置为GlobalResources.xaml中的ResourceDictionary标签:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="YourNamespaceHere.GlobalResources">
您现在可以像这样创建资源字典的实例:
new YourNamespaceHere.GlobalResources()
在您使用资源字典的 WPF 用户控件中,将以下内容添加到构造函数 i UserControl1.xaml.cs:
public UserControl1()
{
if (DesignerProperties.GetIsInDesignMode(this))
this.Resources.MergedDictionaries.Add(new YourNamespaceHere.GlobalResources());
InitializeComponent();
}
现在,使用 UserControl1 的控件的 WinForms 设计器将不再抱怨找不到包含资源字典的 dll。使用过的资源也会显示在设计器中
为确保 WPF 设计器显示 UserControl1 中使用的资源字典中的内容,您仍然需要在 UserControl1.xaml 中添加以下内容:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyDll;component/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
MyDll 是包含资源字典的程序集的名称。在此示例中,GlobalResources.xaml 和 GlobalResources.xaml.cs 应放置在程序集的根级别(不在文件夹中)。
TLDR;
在 运行 时正确地以 VS2015 样式新引用外部 ResourceDictionary
文件,但在设计时不正确。给出了什么?
在工作中,我们有一个 WinForms 产品,其中包含 许多 个 WinForms 屏幕,其中一名开发人员正在积极添加新屏幕,还有一些 WPF 屏幕,我正在添加新屏幕。注意到现有 WPF 屏幕中有很多重复 code/styling,我创建了一个项目来容纳它 - 供所有 existing/future WPF 屏幕引用。
项目: WpfHelper
- 平台目标:任何CPU
- 目标框架:.NET Framework 4.6
WpfHelper.dll
部署到...\Trunk\Project\Externals
...\Trunk\Utilities\WpfHelper\WpfHelper\Resources\GlobalResources.xaml
- 构建操作:页面
- 包含通用样式的 ResourceDictionary
我在六个项目中引用了...\Trunk\Project\Externals\WpfHelper.dll
,将以下代码添加到它们的每个资源文件中:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfHelper;Component/Resources/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
所有屏幕都位于 ...\Trunk\Project\Plugins
。
╔══════════╦═════════════════╦═════════════════╦══════════════════╦════════════════════════════════════════════════╗
║ ║ Resource Works? ║ Platform Target ║ Target Framework ║ Reference File Path ║
╠══════════╬═════════════════╬═════════════════╬══════════════════╬════════════════════════════════════════════════╣
║ Project1 ║ Succeeded ║ Any CPU ║ .NET 4.6 ║ ...\Project1\Project1\Resources\Resources.xaml ║
║ Project2 ║ Succeeded ║ x86 ║ .NET 4.6 ║ ...\Project2\Project2\Resources\Resources.xaml ║
║ Project3 ║ Succeeded ║ Any CPU ║ .NET 4.6 ║ ...\Project3\Project3\Resources\Resources.xaml ║
║ Project4 ║ Failed ║ x86 ║ .NET 4.6 ║ ...\Project4\Project4\Resources\Resources.xaml ║
║ Project5 ║ Failed ║ x86 ║ .NET 4.6 ║ ...\Project5\Project5\Resources\Resources.xaml ║
║ Project6 ║ Failed ║ Any CPU ║ .NET 4.6 ║ ...\Project6\Project6\Resources\Resources.xaml ║
╚══════════╩═════════════════╩═════════════════╩══════════════════╩════════════════════════════════════════════════╝
最近更改
最近我将 Visual Studios 2013 升级到 2015。大约在同一时间,另一个屏幕开发人员将所有现有屏幕项目的目标框架从 .NET Framework 3.5/4.0 升级到 .NET Framework 4.6。
成功项目
- 我在 最近更改 之前引用了
WpfHelper.dll
。 - 样式在设计时和 运行 时正确应用。
失败的项目
- 我在 最近更改 之后引用了
WpfHelper.dll
。 - 样式仅在 运行 次正确应用。
- 在设计时,抛出错误:
An error occurred while finding the resource dictionary "pack://application,,,/WpfHelper;component/Resources/GlobalResources.xaml".
- 使用本地
Resources.xaml
的地方,抛出后续错误:Value cannot be null. Parameter name: item
我试过的:
阅读大量文章和问答后:
- Design Time WPF XAML Resource Dictionaries
- How to load a ResourceDictionary at Design Time in WPF
- Error finding resource dictionary in separate assembly
- Problems loading merged resource dictionaries in .NET 4.0
- Pack URIs in Windows Presentation Foundation
- VS2013: An error occurred while finding the resource dictionary
- An error occurred while finding the resource dictionary
- Error finding merged resource dictionary in another assembly
- Trouble referencing a Resource Dictionary that contains a Merged Dictionary
- WPF VS2013: An error occurred while finding the resource dictionary
- App runs normally but has “errors” during design time: “does not exist in namespace” and “an error occured when finding the resource dictionary”
- Resource Dictionary as Linked File
我尝试了以下所有方法均无济于事:
- 将项目平台目标更改为 "Any CPU"
- 更改项目目标框架 from/to .NET Framework 4.6
- 确保所有 Resource.xaml 文件具有相同的生成操作(页面)等
检查了每个项目的
AssemblyInfo.cs
文件。失败的项目包括(我删除了)以下内容:[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
手动清除 AppsData 中的临时文件夹,清理并重建项目。
- 重新打开项目。
- 重新启动。
- 右键单击从工作项目中复制的
WpfHelper.dll
引用并粘贴到失败项目的引用中。 - 将
WpfHelper.Resources.GlobalResources.xaml
作为链接文件添加到失败的项目中。 - 唠叨每个同事。
- 为
GlobalResources.xaml
中使用的子词典添加了完整包 URI。 - Killed the designer 并重建项目。
我没有想法并且迷失在研究中。我有 templated 一种可行的解决方案,并将其用于创建新屏幕 - 创建在设计时成功显示的新屏幕。这与这些预先存在的屏幕有关。如何让失败的项目在设计时正确显示样式资源?
我已经找到了解决这个问题的方法,实施起来不费吹灰之力。
首先为资源字典添加一个代码隐藏文件,GlobalResources.xaml.cs:
namespace YourNamespaceHere
{
partial class GlobalResources : ResourceDictionary
{
public GlobalResources()
{
InitializeComponent();
}
}
}
然后将x:Class属性设置为GlobalResources.xaml中的ResourceDictionary标签:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="YourNamespaceHere.GlobalResources">
您现在可以像这样创建资源字典的实例:
new YourNamespaceHere.GlobalResources()
在您使用资源字典的 WPF 用户控件中,将以下内容添加到构造函数 i UserControl1.xaml.cs:
public UserControl1()
{
if (DesignerProperties.GetIsInDesignMode(this))
this.Resources.MergedDictionaries.Add(new YourNamespaceHere.GlobalResources());
InitializeComponent();
}
现在,使用 UserControl1 的控件的 WinForms 设计器将不再抱怨找不到包含资源字典的 dll。使用过的资源也会显示在设计器中
为确保 WPF 设计器显示 UserControl1 中使用的资源字典中的内容,您仍然需要在 UserControl1.xaml 中添加以下内容:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyDll;component/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
MyDll 是包含资源字典的程序集的名称。在此示例中,GlobalResources.xaml 和 GlobalResources.xaml.cs 应放置在程序集的根级别(不在文件夹中)。