Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReSharper WPF error: "Cannot resolve symbol "MyVariable" due to unknown DataContext"

I am experiencing this error when using WPF + XAML + MVVM in Visual Studio 2012.

Cannot resolve symbol ”MyVariable“ due to unknown DataContext

What is the solution?

like image 989
Contango Avatar asked Aug 28 '14 13:08

Contango


1 Answers

This error is produced by ReSharper when designing XAML for WPF, and indicates that the XAML cannot find the class that contains run-time bindings. This usually indicates that the DataContext is not set properly.

This error means that:

  • Intellisense for XAML does not work as well at design time;
  • One cannot auto navigate from the XAML to the C# class at design time using a Ctrl-Click on the binding in the XAML;
  • When we select "Find Usages" on a property, it will not bring up the usages in the XAML as well as the C#;
  • The designer cannot not show live data from a custom C# class.

For those of us that think in MVVM, this error indicates that the View cannot find the ViewModel.

Solution 1

Go through some sort of web tutorial to understand how DataBinding works. Recommend Microsoft Data Binding Overview.

Solution 2

If using ReSharper, pressing Alt-Enter on the offending DataContext will bring up a menu that helps you to insert the correct DataContext into your XAML.

I used this to correctly resolve the issue.

enter image description here

Solution 3

In the "Properties" pane of Visual Studio, you can select the data context for the selected control:

enter image description here

Solution 4

Blend can also be used to set the data context. Open up your .sln file in Blend, select the design element, then in the properties select "New":

enter image description here

Solution 5

DevExpress can also help to resolve this error in the XAML for you, using its wizard.

In the XAML, select the parent element you want to set the data context for (usually the entire form), then in the designer select the action triangle.

Then, browse to the class with the C# code.

enter image description here

Hint: The class will be invisible unless you add a parameterless constructor to the class.

XAML before

<UserControl x:Class="DemoAllocation.MyActualView"          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"           mc:Ignorable="d"           d:DesignHeight="300" d:DesignWidth="300"> 

XAML after

<UserControl          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"           xmlns:Implementation="clr-namespace:DemoAllocation.ViewModel.Implementation" x:Class="DemoAllocation.MyActualView"           mc:Ignorable="d"           d:DesignHeight="300" d:DesignWidth="300"> <UserControl.DataContext>     <Implementation:MyActualViewModel/> </UserControl.DataContext> 

Hint 6

If you cannot see the Smart Tags on the WPF designer, check that they have not been switched off at some point:

enter image description here

Solution 7

One can add call a snippet of code on startup that pops up a message box every time there is a binding error. This has turned out to be very useful.

In case the aforementioned web link goes down, here is the code:

public partial class Window1 : Window {   public Window1()   {     BindingErrorTraceListener.SetTrace();     InitializeComponent();   } } 

Method:

using System.Diagnostics; using System.Text; using System.Windows;  namespace SOTC_BindingErrorTracer {   public class BindingErrorTraceListener : DefaultTraceListener   {     private static BindingErrorTraceListener _Listener;      public static void SetTrace()     { SetTrace(SourceLevels.Error, TraceOptions.None); }      public static void SetTrace(SourceLevels level, TraceOptions options)     {       if (_Listener == null)       {         _Listener = new BindingErrorTraceListener();         PresentationTraceSources.DataBindingSource.Listeners.Add(_Listener);       }        _Listener.TraceOutputOptions = options;       PresentationTraceSources.DataBindingSource.Switch.Level = level;     }      public static void CloseTrace()     {       if (_Listener == null)       { return; }        _Listener.Flush();       _Listener.Close();       PresentationTraceSources.DataBindingSource.Listeners.Remove(_Listener);       _Listener = null;     }        private StringBuilder _Message = new StringBuilder();      private BindingErrorTraceListener()     { }      public override void Write(string message)     { _Message.Append(message); }      public override void WriteLine(string message)     {       _Message.Append(message);        var final = _Message.ToString();       _Message.Length = 0;        MessageBox.Show(final, "Binding Error", MessageBoxButton.OK,          MessageBoxImage.Error);     }   } } 

Solution 8

Use the free utility Snoop.

There is a really nice feature that allows you to filter by controls with binding errors. This allows you to navigate straight to the visual with the binding error.

After starting Snoop:

  1. Click and drag the second target icon over your running app.
  2. Hold down Ctrl + Shift.
  3. As you move your mouse over the running app, whatever control is under the mouse will then be outlined in red.
  4. Release the mouse, and Snoop will pop up a window that shows all of the XAML in the visual tree.

enter image description here

enter image description here

Hint 9 - Design Time DataContext

There are actually two completely separate DataContexts: design time and run time.

Most of the previous solutions are focused on setting the run time DataContext.

Once you set the design time DataContext, the XAML preview in Visual Studio or Blend will show custom data provided by your custom C# class.

If using Blend, this custom data can also be read from an XML file, but I prefer to provide it from my own C# class.

To set the design time DataContext, see:

  • Adam Prescott: Design-Time Data Binding in WPF
  • See UI changes in design view with WPF & XAML and data binding?

Or, add this to any element (this will new up the class MyClass at design time, so Intellisense will work):

d:DataContext="{d:DesignInstance d:Type=viewModel:MyClass, IsDesignTimeCreatable=True}" 

And this to the header:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" 

Behind the scenes, when you set the design time DataContext:

  • Visual Studio designer (or Blend) will automatically instantiate a new instance of the class you point it at. This also works if you create a static class.
  • Then, in the XAML preview, as you are editing the XAML, it will display live data from your C# class.
  • This makes designing really fast, as you can work with live data at design time, and you dont have to run the program all the time to see how it looks.

Note that the XAML preview only appears if you are using a User Control. If you prefer to use DataTemplates, no problem: you can create a temporary User Control that includes the DataTemplate, and set the design time DataContext to point at a static class. Code up the static class so that it creates a new instance of your ViewModel (i.e. the class you want to bind to). For example, your static class could read data from a database, populate the properties of the ViewModel, and you could work with live data from the database at XAML design time.

This technique also works perfectly well with Dependency Injection, such as Unity or MEF. You have to point your design time DataContext at a static class which grabs the appropriate classes out of the dependency injection container, and sets everything up. You can then see live data at design time in the XAML preview. The aforementioned links demo how this works (complete with YouTube videos of a live ticking clock at XAML design time!).

Needless to say, this technique works perfectly well with the MVVM pattern, and also with MVVM + Dependency Injection. For those of you unfamiliar with MVVM, its a great way to produce elegant, clean, maintainable and easy-to-alter projects. Microsoft Blend itself is entirely written using the MVVM pattern.

like image 198
Contango Avatar answered Sep 26 '22 23:09

Contango