ReSharper WPF错误:"由于未知的DataContext,无法解析符号"MyVariable"

Con*_*ngo 31 c# wpf xaml mvvm visual-studio-2012

我在Visual Studio 2012中使用WPF + XAML + MVVM时遇到此错误.

由于未知的DataContext,无法解析符号"MyVariable"

解决办法是什么?

Con*_*ngo 97

在为WPF设计XAML时,ReSharper会生成此错误,并指示XAML无法找到包含运行时绑定的类.这通常表示DataContext未正确设置.

此错误意味着:

  • XAML的智能感知在设计时不起作用;
  • 在设计时使用bindingXAML中的Ctrl-Click,无法自动从XAML导航到C#类;
  • 当我们在一个属性上选择"Find Usages"时,它不会提出XAML和C#中的用法;
  • 设计人员无法显示自定义C#类的实时数据.

对于我们这些在MVVM中思考的人来说,这个错误表明View无法找到ViewModel.

解决方案1

通过某种Web教程来了解DataBinding的工作原理.推荐Microsoft数据绑定概述.

解决方案2

如果使用ReSharper,在有问题的DataContext上按Alt-Enter将弹出一个菜单,帮助您将正确的DataContext插入XAML.

我用它来正确解决问题.

在此输入图像描述

解决方案3

在Visual Studio的"属性"窗格中,您可以选择所选控件的数据上下文:

在此输入图像描述

解决方案4

Blend也可用于设置数据上下文.在Blend中打开.sln文件,选择设计元素,然后在属性中选择"新建":

在此输入图像描述

解决方案5

DevExpress还可以使用其向导帮助您在XAML中解决此错误.

在XAML中,选择要为其设置数据上下文的父元素(通常是整个表单),然后在设计器中选择操作三角形.

然后,使用C#代码浏览到该类.

在此输入图像描述

提示:除非向类中添加无参数构造函数,否则该类将不可见.

XAML之前

<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">
Run Code Online (Sandbox Code Playgroud)

XAML之后

<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>
Run Code Online (Sandbox Code Playgroud)

提示6

如果您无法在WPF设计器上看到智能标记,请检查它们是否在某些时候未关闭:

在此输入图像描述

解决方案7

可以在启动时添加调用代码片段,每次出现绑定错误时都会弹出一个消息框.事实证明这非常有用.

如果前面提到的Web链接出现故障,请输入以下代码:

public partial class Window1 : Window
{
  public Window1()
  {
    BindingErrorTraceListener.SetTrace();
    InitializeComponent();
  }
}
Run Code Online (Sandbox Code Playgroud)

方法:

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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

解决方案8

使用免费的实用程序Snoop.

有一个非常好的功能,允许您通过带有绑定错误的控件进行过滤.这允许您直接导航到具有绑定错误的视觉效果.

启动Snoop后:

  1. 在运行的应用上单击并拖动第二个目标图标.
  2. 按住Ctrl + Shift.
  3. 当您将鼠标移动到正在运行的应用程序上时,鼠标下的任何控件都将以红色标出.
  4. 释放鼠标,Snoop将弹出一个窗口,显示可视树中的所有XAML.

在此输入图像描述

在此输入图像描述

提示9 - 设计时DataContext

实际上有两个完全独立的DataContexts:design timerun time.

以前的大多数解决方案都专注于设置run timeDataContext.

设置design timeDataContext后,Visual Studio或Blend中的XAML预览将显示自定义C#类提供的自定义数据.

如果使用Blend,也可以从XML文件中读取此自定义数据,但我更喜欢从我自己的C#类中提供它.

要设置design timeDataContext,请参阅:

或者,将此添加到任何元素(这将MyClass在设计时新增类,因此Intellisense将起作用):

d:DataContext="{d:DesignInstance d:Type=viewModel:MyClass, IsDesignTimeCreatable=True}"
Run Code Online (Sandbox Code Playgroud)

这个标题:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Run Code Online (Sandbox Code Playgroud)

在幕后,当您设置design timeDataContext时:

  • Visual Studio设计器(或Blend)将自动实例化您指向它的类的新实例.如果您创建静态类,这也适用.
  • 然后,在XAML预览中,当您编辑XAML时,它将显示C#类的实时数据.
  • 这使设计变得非常快,因为您可以在设计时使用实时数据,并且您不必一直运行程序以查看它的外观.

请注意,只有在使用用户控件时才会显示XAML预览.如果您更喜欢使用DataTemplates,那么没问题:您可以创建包含DataTemplate的临时用户控件,并将design timeDataContext 设置为指向静态类.对静态类进行编码,以便创建ViewModel的新实例(即要绑定的类).例如,您的静态类可以从数据库读取数据,填充ViewModel的属性,并且您可以在XAML设计时使用数据库中的实时数据.

这种技术也非常适用于依赖注入,例如Unity或MEF.您必须将design timeDataContext 指向一个静态类,该类从依赖项注入容器中获取适当的类,并设置所有内容.然后,您可以在XAML预览中的设计时查看实时数据.上述链接演示了这是如何工作的(在XAML设计时完成了直播时钟的YouTube视频!).

毋庸置疑,这种技术与MVVM模式以及MVVM +依赖注入非常吻合.对于那些不熟悉MVVM的人来说,它是制作优雅,干净,可维护且易于改变的项目的好方法.Microsoft Blend本身完全使用MVVM模式编写.

  • 你也可以设置一个设计时datacontext来解决这个问题:`d:DataContext ="{d:DesignInstance {x:Type localVm:MyViewModel}}"` (7认同)
  • 解决方案2很适合我.简单易行. (2认同)