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

36
在使用Visual Studio 2012中的WPF+XAML+MVVM时,我遇到了这个错误:

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

请问该如何解决?


3
此问题遵循该网站的规则:如果任何用户遇到此特定错误消息,则可以通过谷歌搜索找到解决此错误的步骤。这对其他读者,包括我自己,都非常有用(这个错误相当棘手,我花了一段时间才解决)。 - Contango
3
在我看来,这个问题的内容实在是太少了。经过仔细审核后,我将一些标题中的内容编辑到了正文中,并投票支持重新开放该问题。 - Carrie Kendall
1个回答

113
当使用ReSharper设计WPF的XAML时,如果XAML无法找到包含运行时绑定的类,则会产生此错误。这通常表明 DataContext 未正确设置。
这个错误意味着:
  • XAML的Intellisense在设计时不能很好地工作;
  • 无法通过在XAML中对binding进行Ctrl-Click来自动导航到C#类;
  • 当我们在属性上选择“查找用法”时,它不会在XAML和C#中显示用法;
  • 设计器无法从自定义C#类显示实时数据。
对于那些按照MVVM思想设计的人来说,此错误表示View无法找到ViewModel。

解决方案1

通过某种Web教程了解DataBinding的工作方式。建议使用Microsoft Data Binding Overview

解决方案2

如果使用ReSharper,在有问题的DataContext上按Alt-Enter将会弹出一个菜单,帮助你将正确的DataContext插入到你的XAML中。
我用这个方法成功地解决了问题。

enter image description here

解决方案3

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

enter image description here

解决方案 4

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

enter image description here

解决方案5

DevExpress也可以通过其向导帮助您解决XAML中的错误。

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

然后,浏览到具有C#代码的类。

enter image description here

提示:除非您向类添加一个无参数的构造函数,否则该类将不可见。

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">

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>

提示6

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

enter image description here

解决方案7

可以在启动时添加一段代码片段,每当发生绑定错误时弹出消息框。这被证明非常有用。

如果上述网站链接失效了,这里是代码:

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

方法:

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);
    }
  }
}

解决方案8

使用免费工具Snoop

有一个非常好的功能可以按控件绑定错误进行过滤。这使您可以直接导航到具有绑定错误的可视化界面。

启动Snoop后:

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

enter image description here

enter image description here

提示9 - 设计时的DataContext

实际上有两个完全不同的DataContext:设计时和运行时。

前面的大部分解决方案都是关注设置运行时DataContext。

一旦设置了设计时DataContext,Visual Studio或Blend中的XAML预览将显示自定义C#类提供的自定义数据。

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

要设置设计时DataContext,请参见:

或者,将此代码添加到任何元素中(这将在设计时新建 MyClass 类,因此Intellisense将正常工作):

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

并将此添加到标题:

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

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

请注意,仅当您使用用户控件时,才会出现XAML预览。如果您更喜欢使用DataTemplates,没问题:您可以创建一个临时用户控件,其中包括DataTemplate,并将“设计时”DataContext设置为指向静态类。编写静态类的代码,以便它创建ViewModel的新实例(即您想要绑定到的类)。例如,您的静态类可以从数据库读取数据,填充ViewModel的属性,您可以在XAML设计时使用来自数据库的实时数据。

这种技术也可以与依赖注入(如Unity或MEF)完美配合使用。您需要将设计时DataContext指向一个静态类,该类从依赖注入容器中获取适当的类,并设置所有内容。然后,您可以在XAML预览中实时查看数据。前面提到的链接演示了这种工作方式(包括在XAML设计时间内实时跳动的时钟的YouTube视频!)。
不用说,这种技术也可以与MVVM模式以及MVVM + 依赖注入完美配合使用。对于那些不熟悉MVVM的人来说,它是一种生产优雅、清洁、易于维护和易于修改的项目的好方法。Microsoft Blend本身完全使用MVVM模式编写。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接