TLDR;
Screens newly referencing an external ResourceDictionary
file in VS2015 style correctly at run-time, but not at design-time. What gives?
At work, we have a WinForms product which houses many WinForms screens with one developer actively adding new ones, as well as a handful of WPF screens with me adding new ones. Noticing a lot repetitious code/styling in existing WPF screens, I created a single project to house this - to be referenced by all existing/future WPF screens.
Project: WpfHelper
WpfHelper.dll
deployed to ...\Trunk\Project\Externals
...\Trunk\Utilities\WpfHelper\WpfHelper\Resources\GlobalResources.xaml
I have referenced ...\Trunk\Project\Externals\WpfHelper.dll
in six projects, adding the following code to each of their resource files:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfHelper;Component/Resources/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
All screens are located in ...\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 ║
╚══════════╩═════════════════╩═════════════════╩══════════════════╩════════════════════════════════════════════════╝
Recent Changes
Just recently I upgraded Visual Studios 2013 to 2015. Around the same time, the other screen developer upgraded all existing screen project's target frameworks to .NET Framework 4.6 from .NET Framework 3.5/4.0.
Successful Projects
WpfHelper.dll
prior to the Recent Changes.Failed Projects
WpfHelper.dll
after the Recent Changes.An error occurred while finding the resource dictionary "pack://application,,,/WpfHelper;component/Resources/GlobalResources.xaml".
Resources.xaml
are used, the subsequent error is thrown:
Value cannot be null. Parameter name: item
What I have tried:
After reading an extensive list of articles and Q&A's:
I tried all the following to no avail:
Checked each project's AssemblyInfo.cs
file. Failing projects included (and I removed) the following:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
Manually cleared the temp folder in AppsData, Cleaned & Rebuilt projects.
WpfHelper.dll
references from working projects and pasted into references of failing projects.WpfHelper.Resources.GlobalResources.xaml
as a Linked file to the failed projects.GlobalResources.xaml
.I'm out of ideas and lost in research. I've templated one of the working solutions and used that for creating new screens - that creates new screens which successfully display at design-time. It's something about these pre-existing screens. How can I get the failed projects to correctly display styled resources at design-time?
I have worked out a solution to this problem that takes little effort to implement.
First add a code behind file for the resource dictionary, GlobalResources.xaml.cs:
namespace YourNamespaceHere
{
partial class GlobalResources : ResourceDictionary
{
public GlobalResources()
{
InitializeComponent();
}
}
}
Then set the x:Class property to the ResourceDictionary tag in GlobalResources.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="YourNamespaceHere.GlobalResources">
You are now able to create an instance of the resource dictionary like this:
new YourNamespaceHere.GlobalResources()
In the WPF user control where you are using the resource dictionary, add the following to the constructor i UserControl1.xaml.cs:
public UserControl1()
{
if (DesignerProperties.GetIsInDesignMode(this))
this.Resources.MergedDictionaries.Add(new YourNamespaceHere.GlobalResources());
InitializeComponent();
}
Now the WinForms designer for the control where UserControl1 is used, will no longer complain about not finding your dll containing the resource dictionary. Used resources will also be displayed in the designer.
To make sure the WPF designer will show content from the resource dictionary that is used in UserControl1, you still need the following in your UserControl1.xaml:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyDll;component/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
MyDll is the name of the assembly containing the resource dictionary. In this example GlobalResources.xaml and GlobalResources.xaml.cs are expected to be placed at the root level of the assembly (not in a folder).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With