如何检测破碎的WPF数据绑定?

当试图回答“ unit testingWPF绑定 ”附近的一个问题时,我有以下的小问题。
什么是最好的方式来find,如果你有WPF数据绑定布线设置不正确(或者你刚刚打破了一些连接正确)?

虽然unit testing的方法似乎像Joel的“撕下你的arm去除碎片”..我正在四处寻找更容易的开销方式来检测这一点。

每个人似乎已经承诺与WPF大数据绑定..它确实有其优点。

在.NET 3.5中引入了一种新的方式来专门输出有关特定数据绑定的跟踪信息。

这是通过新的System.Diagnostics.PresentationTraceSources.TraceLevel附加属性完成的,您可以将其应用于任何绑定或数据提供程序。 这里是一个例子:

<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" Title="Debug Binding Sample" Height="300" Width="300"> <StackPanel> <TextBox Name="txtInput" /> <Label> <Label.Content> <Binding ElementName="txtInput" Path="Text" diag:PresentationTraceSources.TraceLevel="High" /> </Label.Content> </Label> </StackPanel> </Window> 

这将在Visual Studio的Output Window中为该特定绑定放置跟踪信息,而不需要任何跟踪configuration。

最好的我可以find…

我怎样才能debuggingWPF绑定? 由Beatriz Stollnitz提供

由于每个人都不能总是留意输出窗口寻找绑定错误,所以我喜欢选项#2。 这是添加到您的App.Config

 <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <sources> <source name="System.Windows.Data" switchName="SourceSwitch" > <listeners> <add name="textListener" /> </listeners> </source> </sources> <switches> <add name="SourceSwitch" value="All" /> </switches> <sharedListeners> <add name="textListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="GraveOfBindErrors.txt" /> </sharedListeners> <trace autoflush="true" indentsize="4"></trace> </system.diagnostics> </configuration> 

配合一个好的正则expression式扫描脚本来提取相关信息,偶尔可以在输出文件夹中的GraveOfBindErrors.txt中运行

 System.Windows.Data Error: 35 : BindingExpression path error: 'MyProperty' property not found on 'object' ''MyWindow' (Name='')'. BindingExpression:Path=MyProperty; DataItem='MyWindow' (Name=''); target element is 'TextBox' (Name='txtValue2'); target property is 'Text' (type 'String') 

您可以使用WPF Inspector的触发器debuggingfunction。 只需从codeplex下载工具,并将其附加到您正在运行的应用程序。 它也显示窗口底部的绑定错误。 非常有用的工具!

在这里输入图像说明

我使用这里介绍的解决scheme将绑定错误转化为本机exception: http : //www.jasonbock.net/jb/Default.aspx? blog= entry.0f221e047de740ee90722b248933a28d

但是,WPF绑定中的正常情况是在用户input无法转换为目标types的情况下抛出exception(例如,将TextBox绑定到整数字段;非数字string的input会导致FormatException,input的数字太大会导致OverflowException)。 类似的情况是,当源属性的Setter引发exception时。

WPF的处理方式是通过ValidatesOnExceptions = true和ValidationExceptionRule来向用户发送提供的input不正确(使用exception消息)。

然而,这些exception也会发送到输出窗口,从而被BindingListener“捕获”,导致错误…显然不是您想要的行为。

因此,我扩展了BindingListener类,在这些情况下不抛出Exception:

 private static readonly IList<string> m_MessagesToIgnore = new List<String>() { //Windows.Data.Error 7 //Binding transfer from target to source failed because of an exception //Normal WPF Scenario, requires ValidatesOnExceptions / ExceptionValidationRule //To cope with these kind of errors "ConvertBack cannot convert value", //Windows.Data.Error 8 //Binding transfer from target to source failed because of an exception //Normal WPF Scenario, requires ValidatesOnExceptions / ExceptionValidationRule //To cope with these kind of errors "Cannot save value from target back to source" }; 

公共覆盖中的修改行void WriteLine(string message)

  .... if (this.InformationPropertyCount == 0) { //Only treat message as an exception if it is not to be ignored if (!m_MessagesToIgnore.Any( x => this.Message.StartsWith(x, StringComparison.InvariantCultureIgnoreCase))) { PresentationTraceSources.DataBindingSource.Listeners.Remove(this); throw new BindingException(this.Message, new BindingExceptionInformation(this.Callstack, System.DateTime.Parse(this.DateTime), this.LogicalOperationStack, int.Parse(this.ProcessId), int.Parse(this.ThreadId), long.Parse(this.Timestamp))); } else { //Ignore message, reset values this.IsFirstWrite = true; this.DetermineInformationPropertyCount(); } } } 

这是一个有效的debugging/跟踪触发器的有用技巧。 它允许您logging所有触发器操作以及正在执行的元素:

http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html

这对我们非常有帮助,但我想添加给那些觉得有用的微软提供的sdk来读取这个文件的工具。

在这里find: http : //msdn.microsoft.com/en-us/library/ms732023.aspx

打开一个跟踪文件

1.使用命令窗口导航到您的WCF安装位置(C:\ Program Files \ Microsoft SDKs \ Windows \ v6.0 \ Bin),启动服务跟踪查看器,然后键入SvcTraceViewer.exe。 (尽pipe我们在\ v7.0 \ Bin中find了我们的)

注意:服务跟踪查看器工具可以关联两种文件types:.svclog和.stvproj。 您可以在命令行中使用两个参数来注册和取消注册文件扩展名。

/ register:用SvcTraceViewer.exe注册文件扩展名“.svclog”和“.stvproj”的关联

/ unregister:使用SvcTraceViewer.exe取消注册文件扩展名“.svclog”和“.stvproj”的关联

1.服务跟踪查看器启动时,单击文件,然后指向打开。 导航到您的跟踪文件存储的位置。

2.双击您要打开的跟踪文件。

注意:按住SHIFT的同时单击多个跟踪文件以select并同时打开它们。 服务跟踪查看器合并所有文件的内容并呈现一个视图。 例如,您可以打开客户端和服务的跟踪文件。 当您在configuration中启用了消息日志logging和活动传播时,这非常有用。 这样,您可以检查客户端和服务之间的消息交换。 您也可以将多个文件拖放到查看器中,或使用“项目”选项卡。 请参阅pipe理项目部分了解更多详情。

3.要将其他跟踪文件添加到打开的集合,请单击“文件”,然后指向“添加”。 在打开的窗口中,导航到跟踪文件的位置,然后双击要添加的文件。

另外,对于日志文件的过滤,我们发现这些链接非常有用:

http://msdn.microsoft.com/en-us/library/ms751526.aspx

对于像我这样的人来说,寻找在给定的跟踪级别启用所有WPF跟踪的纯粹的编程方式,下面是一段代码。 作为参考,它基于这篇文章: 在WPF中跟踪源代码 。

它不需要更改app.config文件,也不需要更改registry。

这是我如何使用它,在一些启动地点(应用程序等):

 .... #if DEBUG WpfUtilities.SetTracing(); #endif .... 

这里是实用程序代码(默认情况下它将所有警告发送给默认跟踪侦听器):

 public static void SetTracing() { SetTracing(SourceLevels.Warning, null); } public static void SetTracing(SourceLevels levels, TraceListener listener) { if (listener == null) { listener = new DefaultTraceListener(); } // enable WPF tracing PresentationTraceSources.Refresh(); // enable all WPF Trace sources (change this if you only want DataBindingSource) foreach (PropertyInfo pi in typeof(PresentationTraceSources).GetProperties(BindingFlags.Static | BindingFlags.Public)) { if (typeof(TraceSource).IsAssignableFrom(pi.PropertyType)) { TraceSource ts = (TraceSource)pi.GetValue(null, null); ts.Listeners.Add(listener); ts.Switch.Level = levels; } } }