Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design-time Error finding the Resource Dictionary - Inconsistent between projects

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

  • Platform target: Any CPU
  • Target framework: .NET Framework 4.6
  • WpfHelper.dll deployed to ...\Trunk\Project\Externals
  • ...\Trunk\Utilities\WpfHelper\WpfHelper\Resources\GlobalResources.xaml
    • Build Action: Page
    • ResourceDictionary containing generic styles

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

  • I referenced WpfHelper.dll prior to the Recent Changes.
  • Styles applied correctly at Design-time and Run-time.

Failed Projects

  • I referenced WpfHelper.dll after the Recent Changes.
  • Styles applied correctly at Run-time only.
  • During Design-time, the error is thrown:

    An error occurred while finding the resource dictionary "pack://application,,,/WpfHelper;component/Resources/GlobalResources.xaml".

  • Where the local 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:

  • 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
  • Visual Studio 2015 XAML Resource Dictionary Error

I tried all the following to no avail:

  • Change project Platform target to "Any CPU"
  • Change project Target framework from/to .NET Framework 4.6
  • Ensure all Resource.xaml files had the same Build Action (Page), etc.
  • 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.

  • Re-opened projects.
  • Rebooted.
  • Right-click copied WpfHelper.dll references from working projects and pasted into references of failing projects.
  • Added the WpfHelper.Resources.GlobalResources.xaml as a Linked file to the failed projects.
  • Nagged every co-worker.
  • Added the full pack URI for sub-dictionaries used in GlobalResources.xaml.
  • Killed the designer and rebuilt the project.

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?

like image 291
OhBeWise Avatar asked Dec 08 '15 21:12

OhBeWise


1 Answers

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).

like image 169
Christian Myksvoll Avatar answered Oct 20 '22 19:10

Christian Myksvoll