我想以某种方式确保我在xaml中的所有绑定都绑定到现有属性。
我想避免这样的运行时错误:
BindingExpression path error: 'Fullname' property not found on 'object' ''Person' (HashCode=33132859)'.
BindingExpression:Path=Person.Fullname; DataItem='ViewModel' (HashCode=46007650); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
每个视图都使用d:DesignInstance指定了数据上下文的类型,如果无法从上下文继承,则每个DataTemplate都使用DataType属性(例如ListBoxItem模板)。
在visualstudioxaml设计器中,无效的属性会加下划线,运行时我会在输出窗口中出现绑定错误。
有什么工具可以检查这些错误吗?我在考虑一些自动化的UI测试,它将遍历整个应用程序并检查调试输出,但设置起来相当困难。
如果resharper能够解析xaml并识别无效绑定,那么至少从理论上讲,在代码分析系统或单元测试中应该可以这样做。
编辑:我在用户语音中添加了建议:https://wpf.uservoice.com/forums/40688-general/suggestions/7423474-strongly-typed-binding-testability请投票!
我喜欢这个解决方案:https://web.archive.org/web/20130505005640/http://tech.pro/tutorial/940/wpf-检测绑定错误的代码段。每次绑定失败时,您都会收到一条弹出消息。
编辑:根据请求,这里是BindingErrorTraceListener的源代码,由Michael Kuehl编写,包括Jesse Chisholm的错误修复(通过Dispatcher将MessageBox发送到GUI线程)。
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;
Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new System.Windows.Threading.DispatcherOperationCallback(delegate { MessageBox.Show(final, "Binding Error", MessageBoxButton.OK,
MessageBoxImage.Error); return null; }),
null);
}
}
}
然后,在Window或View基类中,添加行
BindingErrorTraceListener.SetTrace();
打开弹出窗口。