Debug Databinding Issues in WPF

DataBinding is one of the most powerful features in WPF. But because it resolves the bindings at runtime and does not throw exceptions, it's sometimes hard to find the reason why the data do not appear as expected. There are mainly two reasons:

  • The DataBinding expression is invalid. Then use Trace Output to resolve.
  • The DataBinding expression is valid, but the result is not the expected. Then use a Debug Converter to resolve it.

Method 1: Trace messages in the output window

In the example, the text property of the TextBlock is bound to the property "InvalidPath" of the StackPanel - which does not exists.

<Window x:Class="DebugDataBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <StackPanel x:Name="stack">
        <TextBlock Text="{Binding ElementName=stack, Path=InvalidPath}" />
    </StackPanel>
</Window>

 

In this case the invalid databinding expression is reported by a trace message in the output window

System.Windows.Data Error: 39 : BindingExpression path error: 'InvalidPath' property not found on 'object' ''StackPanel' (Name='stack')'. BindingExpression:Path=InvalidPath; DataItem='StackPanel' (Name='stack'); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Note: Binding to a path of a property that has NULL value is a valid expression and does not generate an error message (for e.g. binding to a property of the data context that is NULL).

Adjust the trace level (.NET 3.5 and higher)

NET3.5 has a new feature that allows you to set the level of details of trace messages to NoneLowMedium or High.

To set the trace level you have to include an extra namespace to your XAML:

复制代码
 
<Window x:Class="DebugDataBinding.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">
 
    <StackPanel x:Name="stack">
        <TextBlock Text="{Binding ElementName=stack, Path=InvalidPath, 
                          diag:PresentationTraceSources.TraceLevel=High}" />
    </StackPanel>
</Window>
复制代码

 

The following snipped shows how to adjust the trace level by code:

 
PresentationTraceSources.DataBindingSource.Listeners.Add(
                    new ConsoleTraceListener());
 
PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.All;


Method 2: Use a ValueConverter to break into the debugger

A simple trick is to write a value converter that does nothins except breaking into the debugger. All you need to do now is to add this converter to the binding expression that fails and you can easily see the values that should be bound.

 
复制代码
/// <summary>
/// This converter does nothing except breaking the
/// debugger into the convert method
/// </summary>
public class DatabindingDebugConverter : 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;
    }
}
复制代码

 

To use the converter in XAML, reference the namespace of the assembly that contains the converter and add an instance of it to the resources of your window.

 
复制代码
<Window x:Class="DebugDataBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DebugDataBinding"
    Title="Window1" Height="300" Width="300">
 
    <Window.Resources>
        <local:DatabindingDebugConverter x:Key="debugConverter" />
    </Window.Resources>
 
    <StackPanel x:Name="stack">
        <TextBlock Text="{Binding ElementName=stack, Path=ActualWidth, 
                          Converter={StaticResource debugConverter}}" />
    </StackPanel>
</Window>
复制代码

 

以上原文链接

 

另外还有一些可选的配置文件:

复制代码
<configuration>

  <system.diagnostics>
    <sources>
      
      <!--<source name="System.Windows.Data" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>-->      

      
      <!--<source name="System.Windows.DependencyProperty" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>-->
      

      <!--
      <source name="System.Windows.Freezable" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->

      <!--
      <source name="System.Windows.RoutedEvent" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->

      <!--
      <source name="System.Windows.Media.Animation" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->

      <!--
      <source name="System.Windows.NameScope" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->

      <!--
      <source name="System.Windows.ResourceDictionary" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->

      <!--
      <source name="System.Windows.Markup" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->

      <!--
      <source name="System.Windows.Documents" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>
      -->
    </sources>

    <switches>
      <add name="SourceSwitch" value="Off" />
      <!--<add name="SourceSwitch" value="All" />-->
      
      <!--<add name="SourceSwitch" value="Verbose" />-->
      <!--<add name="SourceSwitch" value="Warning" />-->
      <!--<add name="SourceSwitch" value="Activity" />-->
    </switches>

    
    <sharedListeners>
      <!-- This listener sends output to the console -->
      <add name="console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false"/>

      <!-- This listener sends output to an Xml file named AvTrace.xml -->
      <!--<add name="xmlListener" type="System.Diagnostics.XmlWriterTraceListener" traceOutputOptions="None" initializeData="AvTrace.xml" />-->

      <!-- This listener sends output to a file named AvTrace.txt -->
      <!--<add name="textListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="AvTrace.txt" />-->
    </sharedListeners>

    <trace autoflush="true" indentsize="4"></trace>
    
  </system.diagnostics>
</configuration>
App.Config 可选配置项
复制代码

 

 

posted @   把爱延续  阅读(560)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
历史上的今天:
2010-10-12 SQLite 性能优化
2010-10-12 SQLite 查询优化
2010-10-12 SQLite FAQ
点击右上角即可分享
微信分享提示