此错误是 ReSharper 在为 WPF 设计 XAML 时产生的,表示 XAML 找不到包含运行时绑定的类。这通常表示DataContext 设置不正确。
这个错误意味着:
- Intellisense for XAML 在设计时无法正常工作;
- 无法在设计时使用 Ctrl 键单击 XAML 中的
binding,从 XAML 自动导航到 C# 类;
- 当我们在属性上选择“查找用法”时,它不会显示 XAML 和 C# 中的用法;
- 设计器不能显示来自自定义 C# 类的实时数据。
对于我们这些在 MVVM 中思考的人来说,这个错误表明 View 找不到 ViewModel。
解决方案 1
通过某种网络教程来了解 DataBinding 的工作原理。推荐Microsoft Data Binding Overview。
解决方案 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">
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 设计器上看不到智能标记,请检查它们是否在某个时候被关闭:
解决方案 7
可以添加调用snippet of code on startup,每次出现绑定错误时都会弹出一个消息框。事实证明这非常有用。
万一上述网页链接失效,代码如下:
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 后:
- 单击第二个目标图标并将其拖动到正在运行的应用程序上方。
- 按住 Ctrl + Shift。
- 当您将鼠标移到正在运行的应用程序上时,鼠标下方的任何控件都将显示为红色。
- 松开鼠标,Snoop 将弹出一个窗口,在可视化树中显示所有 XAML。
提示 9 - 设计时数据上下文
实际上有两个完全独立的 DataContext:design time 和 run time。
以前的大多数解决方案都侧重于设置run time DataContext。
设置design time DataContext 后,Visual Studio 或 Blend 中的 XAML 预览将显示自定义 C# 类提供的自定义数据。
如果使用 Blend,也可以从 XML 文件中读取此自定义数据,但我更喜欢从我自己的 C# 类中提供它。
要设置design time 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"
在幕后,当你设置design time DataContext:
- Visual Studio 设计器(或 Blend)将自动实例化您指向的类的新实例。如果您创建一个静态类,这也适用。
- 然后,在 XAML 预览中,当您编辑 XAML 时,它将显示来自 C# 类的实时数据。
- 这使得设计速度非常快,因为您可以在设计时使用实时数据,而不必一直运行程序来查看它的外观。
请注意,只有在您使用用户控件时才会显示 XAML 预览。如果您更喜欢使用 DataTemplates,没问题:您可以创建一个包含 DataTemplate 的临时用户控件,并将 design time DataContext 设置为指向静态类。编写静态类,以便它创建 ViewModel 的新实例(即要绑定到的类)。例如,您的静态类可以从数据库中读取数据,填充 ViewModel 的属性,并且您可以在 XAML 设计时使用数据库中的实时数据。
这种技术也适用于依赖注入,例如 Unity 或 MEF。您必须将 design time DataContext 指向一个静态类,该类从依赖注入容器中获取适当的类,并设置所有内容。然后,您可以在设计时在 XAML 预览中查看实时数据。上述链接演示了它是如何工作的(在 XAML 设计时,还附有 YouTube 实时时钟视频!)。
不用说,这种技术非常适用于 MVVM 模式,也适用于 MVVM + 依赖注入。对于那些不熟悉 MVVM 的人来说,它是生成优雅、干净、可维护和易于更改的项目的好方法。 Microsoft Blend 本身完全使用 MVVM 模式编写。