[WPF] 如何调试Data Binding

简介: 原文:[WPF] 如何调试Data Binding前言 在WPF开发中,将ViewModel中对象绑定到UI上时,会出现明明已经将数据对象Binding到UI,但是UI上就是不显示等等的问题。这篇博客将介绍WPF Data Binding调试相关的内容。
原文: [WPF] 如何调试Data Binding

前言

在WPF开发中,将ViewModel中对象绑定到UI上时,会出现明明已经将数据对象Binding到UI,但是UI上就是不显示等等的问题。这篇博客将介绍WPF Data Binding调试相关的内容。

场景一(Binding的属性不存在)

ViewModel:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel() { Id = 100, Name = "Tom", Age = 24};
    }
}

public class ViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

XAML:

<StackPanel Margin="10">
    <TextBlock Text="{Binding ID}" />
    <TextBlock Text="{Binding Name}" Margin="0,10" />
    <TextBlock Text="{Binding Age}" />
</StackPanel>

运行结果:

UI中Binding的ID值没有显示出来。请注意加粗的代码,在UI代码中,由于拼写错误,将Id写成了ID。但是这段代码在编译时不会报错,在VS Output窗口中也不会有提示/警告信息。在程序运行时,仔细查看VS Output窗口,此时会有如下信息 (对信息进行了精简)
System.Windows.Data Error: 40 : BindingExpression path error: 'ID' property not found on 'object' ''ViewModel' (HashCode=20915929)'. BindingExpression:Path=ID; DataItem='ViewModel' (HashCode=20915929); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

这段信息告诉提示说在ViewModel对象上没有找到ID属性,此时我们再去检查一下ViewModel发现,原来是将Id错误的写成了ID。一般这种错误的提示开头为:System.Windows.Data Error:

场景二(使用System.Diagnostics来追踪)

XAML:

<Window x:Class="WpfBindingDebug.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock Text="{Binding Title}" />
    </StackPanel>
</Window>

将Title属性Binding到TextBlock的Text属性上面,XAML和C#代码中均未指定DataContext属性。编译项目并运行程序,在VS Output中没有任何提示/警告信息。此时应该如何调试呢?可以通过设置PresentationTraceSources对象的TraceLevel来强制WPF输出所有的Binding方面的信息。

更多PresentationTraceSources信息可以参考:

https://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.tracelevel(v=vs.110).aspx

对XAML代码进行如下修改(注意加粗的代码行):

<Window x:Class="WpfBindingDebug.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock Text="{Binding Title, diag:PresentationTraceSources.TraceLevel=High}" />
    </StackPanel>
</Window>

编译并运行程序,在VS Output窗口中可以找到关于Binding的信息(对信息进行了精简):

System.Windows.Data Warning: 56 : Created BindingExpression (hash=39201736) for Binding (hash=44325851)
System.Windows.Data Warning: 58 :   Path: 'Title'
System.Windows.Data Warning: 60 : BindingExpression (hash=39201736): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=39201736): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=39201736): Attach to System.Windows.Controls.TextBlock.Text (hash=17911681)
System.Windows.Data Warning: 67 : BindingExpression (hash=39201736): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=39201736): Found data context element: TextBlock (hash=17911681) (OK)
....
System.Windows.Data Warning: 67 : BindingExpression (hash=39201736): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=39201736): Found data context element: TextBlock (hash=17911681) (OK)
System.Windows.Data Warning: 71 : BindingExpression (hash=39201736): DataContext is null
System.Windows.Data Warning: 67 : BindingExpression (hash=39201736): Resolving source  (last chance)
System.Windows.Data Warning: 70 : BindingExpression (hash=39201736): Found data context element: TextBlock (hash=17911681) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=39201736): Activate with root item <null>
System.Windows.Data Warning: 106 : BindingExpression (hash=39201736):   Item at level 0 is null - no accessor
System.Windows.Data Warning: 80 : BindingExpression (hash=39201736): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=39201736): TransferValue - using fallback/default value ''
System.Windows.Data Warning: 89 : BindingExpression (hash=39201736): TransferValue - using final value ''

注意:在Visual Studio 2010中需要进行如下设置才能看到上面的提示信息:因为VS 2010默认将下面的设为Off。

Tools -> Options -> Debugging -> Output Window -> WPF Trace Settings -> Data Binding -> set to Warning

程序一直在尝试寻找Visual Tree上的可以Binding的Title值,最终找到一个合适的,DependencyProperty.UnsetValue。

上述方法对查找单个页面Binding很有用,当然我们也可以全局的来收集这些Binding信息。在App.xaml.cs中添加:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        PresentationTraceSources.Refresh();
        PresentationTraceSources.DataBindingSource.Listeners.Add(new ConsoleTraceListener());
        PresentationTraceSources.DataBindingSource.Listeners.Add(new DebugTraceListener());
        PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Warning | SourceLevels.Error;
        base.OnStartup(e);
    }
}

public class DebugTraceListener : TraceListener
{
    public override void Write(string message)
    {
        // Write your log here.
    }

    public override void WriteLine(string message)
    {
        // Write your log here.
    }
}

场景三(使用ValueConverter来调试)

场景一和场景二中的方法解决因拼写错误或者无明确DataContext时非常有效。不过有时候真正的通过VS进行调试一下,更加直观,便捷。可以使用实现一个简单的调试使用的Converter,然后将其Binding到目标上,

public class DebugConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Debugger.Break();
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Debugger.Break();
        return value;
    }
}

Debugger.Break()的效果和VS中F9设置断点是一样的。
XAML

<Window x:Class="WpfBindingDebug.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfBindingDebug"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:DebugConverter x:Key="DebugConverter" />
    </Window.Resources>
    <StackPanel>
        <TextBlock Text="{Binding Id, Converter={StaticResource DebugConverter}}" />
    </StackPanel>
</Window>

感谢您的阅读~如果您有其他关于Data Binding的调试方式,欢迎在评论区指出~

目录
相关文章
|
8月前
|
存储 自然语言处理 C#
WPF技术之Binding
WPF(Windows Presentation Foundation)是微软推出的一种用于创建应用程序用户界面的框架。Binding(绑定)是WPF中的一个重要概念,它用于在界面元素和数据源之间建立关联。通过Binding,可以将界面元素(如文本框、标签、列表等)与数据源(如对象、集合、属性等)进行绑定,从而实现数据的双向传递和同步更新。
142 2
WPF技术之Binding
|
C#
WPF QuickStart系列之数据绑定(Data Binding)
原文:WPF QuickStart系列之数据绑定(Data Binding) 这篇博客将展示WPF DataBinding的内容。 首先看一下WPF Data Binding的概览, Binding Source可以是任意的CLR对象,或者XML文件等,Binding Target需要有依赖属性。
1164 0
|
数据可视化 C# DataX
WPF 的 ElementName 在 ContextMenu 中无法绑定成功?试试使用 x:Reference!
原文:WPF 的 ElementName 在 ContextMenu 中无法绑定成功?试试使用 x:Reference! 版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
1214 0
|
C#
解答WPF中ComboBox SelectedItem Binding不上的Bug
原文:解答WPF中ComboBox SelectedItem Binding不上的Bug 正在做一个打印机列表,从中选择一个打印机(System.Printing) var printServer = new LocalPrintServer(); PrintQueues = printServer.
969 0
|
C#
WPF Binding Mode,UpdateSourceTrigger
原文:WPF Binding Mode,UpdateSourceTrigger WPF 绑定模式(mode) 枚举值有5个1:OneWay(源变就更新目标属性)2:TwoWay(源变就更新目标并且目标变就更新源)3:OneTime(只根据源来设置目标,以后都不会变)4:OneWayToSource...
1517 0
|
C#
Enum Binding ItemsSource In WPF
原文:Enum Binding ItemsSource In WPF在WPF中枚举绑定到ItemsSource。 一、通过ObjectDataProvider 获取Enum数据源 首先我们定义一个Enum类: public enum TableSelectedType { SelectedOne, SelectedTwo, SelectedThird } 接着在Xaml中的Resource里定义数据源。
668 0
|
C#
【WPF】wpf用MultiBinding解决Converter需要动态传参的问题,以Button为例
原文:【WPF】wpf用MultiBinding解决Converter需要动态传参的问题,以Button为例       用Binding并通过Converter转换的时候,可能偶尔会遇到传参的问题,一般通过设置xaml中的BindingParameter属性来给Converter传递参数。
1892 0
|
存储 算法 测试技术
WPF---Binding学习(一)
转自:http://blog.csdn.net/lisenyang/article/details/18312199 1,Data Binding在WPF中的地位 程序的本质是数据+算法。数据会在存储、逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要。
1159 0
|
XML .NET 程序员
WPF Binding学习(四) 绑定各种数据源
转自:http://blog.csdn.net/lisenyang/article/details/18312199 1.集合作为数据源    首先我们先创建一个模型类 public class Student { public int ID { get; set; } ...
1369 0