在Visual Studio 2012中使用WPF + XAML + MVVM时遇到此错误。
由于未知的DataContext
,无法解析符号“MyVariable”
解决方案是什么?
答案 0 :(得分:94)
在为WPF设计XAML时,ReSharper会生成此错误,并指示XAML无法找到包含运行时绑定的类。这通常表示DataContext
未正确设置。
此错误表示:
binding
按住Ctrl键单击,无法自动从XAML导航到C#类; 对于我们这些在MVVM中思考的人来说,这个错误表明View无法找到ViewModel。
通过某种Web教程来了解DataBinding的工作原理。建议Microsoft Data Binding Overview。
如果使用ReSharper,在有问题的DataContext上按Alt-Enter将弹出一个菜单,帮助您将正确的DataContext插入XAML。
我用它来正确解决问题。
在"属性"在Visual Studio窗格中,您可以选择所选控件的数据上下文:
Blend也可用于设置数据上下文。在Blend中打开你的.sln文件,选择设计元素,然后在属性中选择" New":
DevExpress还可以使用其向导帮助您在XAML中解决此错误。
在XAML中,选择要为其设置数据上下文的父元素(通常是整个表单),然后在设计器中选择动作三角形。
然后,使用C#代码浏览到该类。
提示:除非您向该类添加无参数构造函数,否则该类将不可见。
<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">
<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>
如果您无法在WPF设计器上看到智能标记,请检查它们是否在某些时候没有关闭:
每次有绑定错误时,可以添加一个弹出消息框的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);
}
}
}
使用免费实用程序Snoop。
有一个非常好的功能,允许您通过带有绑定错误的控件进行过滤。这允许您直接导航到具有绑定错误的视觉效果。
启动Snoop之后:
实际上有两个完全独立的DataContexts: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:
请注意,只有在使用用户控件时才会显示XAML预览。如果您更喜欢使用DataTemplates,则没有问题:您可以创建包含DataTemplate的临时用户控件,并将design time
DataContext设置为指向静态类。对静态类进行编码,以便创建ViewModel的新实例(即要绑定到的类)。例如,您的静态类可以从数据库读取数据,填充ViewModel的属性,并且您可以在XAML设计时使用数据库中的实时数据。
这种技术也非常适用于依赖注入,例如Unity或MEF。您必须将design time
DataContext指向一个静态类,该类从依赖项注入容器中获取相应的类,并设置所有内容。然后,您可以在XAML预览中的设计时查看实时数据。上述链接演示了这是如何工作的(在XAML设计时完成了直播时钟的YouTube视频!)。
毋庸置疑,这种技术与MVVM模式以及MVVM +依赖注入完美配合。对于那些不熟悉MVVM的人来说,它是制作优雅,干净,可维护且易于改变的项目的好方法。 Microsoft Blend本身完全使用MVVM模式编写。