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

Gis*_*shu 70 data-binding wpf

在尝试回答" 单元测试WPF绑定 " 附近的问题时,我遇到了以下琐碎的问题.
如果您的WPF数据绑定布线设置不正确(或者您刚刚破坏了正确接线的东西),最好的方法是什么? ?

虽然单元测试方法似乎就像Joel的"扯掉你的手臂去除碎片"......我正在四处寻找更容易,更少的开销方式来检测这一点.

每个人似乎都已经在WPF中大力宣传数据绑定......它确实有其优点.

Enr*_*lio 68

在.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>
Run Code Online (Sandbox Code Playgroud)

这将在Visual Studio的输出窗口中为该特定绑定提供跟踪信息,而无需任何跟踪配置.


Gis*_*shu 39

我能找到最好的......

如何调试WPF绑定?作者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>
Run Code Online (Sandbox Code Playgroud)

将其与良好的正则表达式扫描脚本配对以提取相关信息,您可以偶尔在输出文件夹中的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')
Run Code Online (Sandbox Code Playgroud)


小智 6

我使用这里提供的解决方案将绑定错误转换为本地异常:http : //www.jasonbock.net/jb/Default.aspx? blog= entry.0f221e047de740ee90722b248933a28d

但是,WPF 绑定中的正常情况是在用户输入无法转换为目标类型的情况下抛出异常(例如,绑定到整数字段的 TextBox;非数字字符串的输入导致 FormatException,输入过大的数字会导致溢出异常)。类似的情况是 source 属性的 Setter 抛出异常。

WPF 处理此问题的方法是通过 ValidatesOnExceptions=true 和 ValidationExceptionRule 向用户发出信号,提供的输入不正确(使用异常消息)。

但是,这些异常也会发送到输出窗口,因此被 BindingListener '捕获',导致错误......显然不是您想要的行为。

因此,我将BindingListener类扩展为在这些情况下不会抛出异常:

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"  
        };
Run Code Online (Sandbox Code Playgroud)

public override 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();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以使用WPF Inspector的触发器调试功能.只需从codeplex下载该工具并将其附加到正在运行的应用程序即可.它还显示窗口底部的绑定错误.非常有用的工具!

在此输入图像描述