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

3

6

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.

Chandler answered 13/4, 2011 at 15:28 Comment(0)
M
3

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.

Micahmicawber answered 14/4, 2011 at 14:36 Comment(2)
Hi, thanks for the (sad) explanation. I did make some headway into what's happening here, and I just noticed that the resources that are listed as local in the pop-up window are actually global resources defined in the app.xaml. The ones defined in the Window.Resources section of the XAML are not listed at all. So I guess my question is why the window resources aren't listed, and how I am supposed to use them (without writing the XAML manually, which isn't the end of the world, but shouldn't be necessary for something like this).Chandler
I voted for that suggestion, and I also submitted this as an indiviual bug at connect.microsoft.com/VisualStudio/feedback/details/666201/… so please vote for it, and let's see if we can improve the XAML support in VS.Chandler
E
2

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

Elemental answered 20/1, 2017 at 15:18 Comment(2)
Thanks for the reply. Interesting idea, have to give it a go!Chandler
You're welcome. It's something that has bothering me for years. It should have been fixed a long time ago. If the XAML runtime can find it, then Intellisense should always be able to find it too, even if it has to look in parent projects for the definition.Elemental
E
0

I had a similar issue that was caused by the style resources' build action, which was set to "Resource" (sounds appropriate doesn't it). I changed the "Build action" to "Page", in the properties panel for each resource xaml file (e.g. Colors.xaml, Icons.xaml, Styles.xaml). Then Visual Studio suddenly recognized all my StaticResource references.

Erring answered 24/1 at 10:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.