Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio can't resolve static resource in WPF window, even though it works at run time - why?

I have a WPF window and am using the MVVM pattern. I set the view model as a resource for the window as follows...

<Window
  ...other stuff removed for clarity...
  xmlns:mvvm="clr-namespace:VisionRT.CRM.WPF.ViewModels.VRTSystems"
>
<Window.Resources>
  <mvvm:DhrTemplatesViewModel x:Key="viewmodel" />
</Window.Resources>

I want to set the window's data context to use the resource, and found that the following XAML works...

  <Window.DataContext>  
    <StaticResource ResourceKey="viewmodel"/> 
  <Window.DataContext> 

The problem is that I can only do this by typing the XAML manually, Visual Studio doesn't show the resource anywhere. I can go to the window's properties and click the little icon next to the DataContext property, click the "Apply resource" option, but it doesn't show "viewmodel" as a resource, static or dynamic. If I enter the XAML manually and then open the "Apply resource" pop-up window, it has the "viewmodel" underlined as an error, and hovering over it shows a tooltip "cannot resolve resource reference"

However, when I run the application, it works fine, so the resource is being resolved at run time.

Anyone able to explain this? I would really like to be able to do this through the VS property editor, as I find that more convenient than typing the XAMl by hand. I'm also bothered by the fact that VS can't resolve it. This makes me think I'm doing something wrong.

Thanks for any explanation you can give.

like image 529
Avrohom Yisroel Avatar asked Oct 11 '22 07:10

Avrohom Yisroel


2 Answers

The only (sad) explanation is that XAML is a second grade citizen in Visual Studio. Once you start pushing XAML a little more than basic and you end up with "unresolved" "cant display" "sorry I'm dumb", etc.

Refer to this WPF suggestion: http://dotnet.uservoice.com/forums/40583-wpf-feature-suggestions/suggestions/480899-make-xaml-a-first-class-citizen-of-visual-studio?ref=title to get them fixed.

like image 117
Eduardo Molteni Avatar answered Jan 01 '23 11:01

Eduardo Molteni


It is possible to make Intellisense work 100% for a XAML {StaticResource} in Visual Studio.

Tested On

  • WPF/C#
  • Visual Studio 2015 Update 3

Step 1: Shift resources into shared project

The key is to shift all resources referenced by ResourceDictionary into a shared project:

enter image description here

Step 2: Design time intellisense

We're not quite there yet. The XAML runtime throws runtime if you include resources twice.

If we are including an .xaml file more than once in the entire project, we can include it at design time, but not at runtime:

public class DesignTimeResourceDictionary : ResourceDictionary
{
    private Uri source;

    public new Uri Source
    {
        get
        {
            if ((bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)
            {
                return null;
            }

            return this.source;
        }
        set { this.source = value; }
    }
}

Then we can add design time resources:

<!--Design time resource dictionary, so intellisense will work with with {StaticResource}.-->
<ResourceDictionary.MergedDictionaries>
    <dr:DesignTimeResourceDictionary Source="/Project.Name;component/Folder/SharedResourceA.xaml" />
    <dr:DesignTimeResourceDictionary Source="/Project.Name;component/Folder/SharedResourceB.xaml" />
</ResourceDictionary.MergedDictionaries>

If we are using ReSharper, it will offer to automatically add the namespace prefix into the header:

xmlns:dr="clr-namespace:MyNamespace;assembly=Project.Name"

Appendix A: Extra for Experts: Why the need for Step 1?

As an aside, Intellisense in XAML is the same as Intellisense in C#: it only works with sub-projects that are referenced. This is why if projects A and B want to share some code, you must put it in a class library C that is referenced by projects A and B. This is in contrast to C or C++ where #including a file in the root makes it available to all subfiles.

With XAML, you can cheat and add static resources into Main Application Project (above), and the XAML runtime will still work properly - but Intellisense won't work at design time, presumably as its based on the same engine that is used for C# intellisense.

To make Intellisense work all the time in XAML, Visual Studio Intellisense would have to scan up through every parent project (instead of just down towards referenced projects).

like image 32
Contango Avatar answered Jan 01 '23 11:01

Contango