More on debugging DependencyProperty

In the previous post on DependencyPropertyHelper, we explored one way of debugging the Dependency Properties.

The DepedencyPropertyHelper provides you details on from which value provider the final value was calculated from. However, if you want to trace and ensure the binding has been set correctly, you could make use of PresentationTraceSources.

For example, consider following binding.

<Button Content="{Binding ButtonTitle}"/>

To enable tracing, one could enable the PresentationTraceSources as,

<Button Content="{Binding ButtonTitle, diag:PresentationTraceSources.TraceLevel=High}"/>

Do not forget to add reference to System.Diagnostics

xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"

Now your output window would have the entire trace.

System.Windows.Data Warning: 60 : BindingExpression (hash=28316044): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=28316044): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=28316044): Attach to System.Windows.Controls.Button.Content (hash=17324607)
System.Windows.Data Warning: 67 : BindingExpression (hash=28316044): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=28316044): Found data context element: Button (hash=17324607) (OK)
System.Windows.Data Warning: 71 : BindingExpression (hash=28316044): DataContext is null
System.Windows.Data Warning: 65 : BindingExpression (hash=28316044): Resolve source deferred
System.Windows.Data Warning: 67 : BindingExpression (hash=28316044): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=28316044): Found data context element: Button (hash=17324607) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=28316044): Activate with root item ShellViewModel (hash=18700393)
System.Windows.Data Warning: 108 : BindingExpression (hash=28316044):   At level 0 - for ShellViewModel.ButtonTitle found accessor RuntimePropertyInfo(ButtonTitle)
System.Windows.Data Warning: 104 : BindingExpression (hash=28316044): Replace item at level 0 with ShellViewModel (hash=18700393), using accessor RuntimePropertyInfo(ButtonTitle)
System.Windows.Data Warning: 101 : BindingExpression (hash=28316044): GetValue at level 0 from ShellViewModel (hash=18700393) using RuntimePropertyInfo(ButtonTitle): 'Proceed'
System.Windows.Data Warning: 80 : BindingExpression (hash=28316044): TransferValue - got raw value 'Proceed'
System.Windows.Data Warning: 89 : BindingExpression (hash=28316044): TransferValue - using final value 'Proceed'

You could also set write custom TraceListener to break at the binding error. For example,

PresentationTraceSources.Refresh();
PresentationTraceSources.DataBindingSource.Listeners.Add(new ConsoleTraceListener());
PresentationTraceSources.DataBindingSource.Listeners.Add(new DebugTraceListener());
PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error;

Where DebugTraceListener is defined as

public class DebugTraceListener : TraceListener
{
    public override void Write(string message)
    {
    }

    public override void WriteLine(string message)
    {
        Debugger.Break();
    }
}

This would ensure a break point is hit whenever encountered with a missing binding.

DependencyPropertyHelper.GetValueSource : Debugging Helper for Dependency Properties

DependencyPropertyHelper.GetValueSource is a great debugging aid in detecting the source of value of a Dependency Property. This is quite useful for WPF developers who might need to figure out the source which provides the current value for the Dependency Property.

The DependencyPropertyHelper.GetValueSource returns a structure ValueSource which has 5 Properties.

  • BaseValueSource
  • IsAnimated
  • IsCoerced
  • IsCurrent
  • IsExpression
DependencyPropertyHelper.GetValueSource(buttonControl,CustomValueProperty)
{System.Windows.ValueSource}
    BaseValueSource: Local
    IsAnimated: false
    IsCoerced: false
    IsCurrent: false
    IsExpression: true

Dependency Property Value Precedence

The value of Dependency Property is calculated in 5 Steps.

  • Calculate the Base Value
  • Evaluate Expression if any
  • Apply Animation if any
  • Coerce Value

The BaseValueSource in the ValueSource structure speficies how the Base Value of the Dependency property is calculated. The base value of Dependency Property is calculated with aid of property value providers. Some ofthe Value Providers in decreasing Order of precedence are

  • Local Value
  • Templated Parent
  • Implicit style
  • Style triggers
  • Template Triggers
  • Style Setters
  • Theme
  • Inheritence
  • Default Value

Once the base value has been determined, the value is then passed through a series of steps depending on how the value is configured. These include Expressions, Animations and coerce callbacks if they are configured. You can follow more details on Dependency Property Value Precedence in the MSDN documentation

The DependencyPropertyHelper.GetValueSource provides an indication on how the current value in Dependency Property has been determined.

Customized Debugger Tooltip

Code-Execute-Debug-Code-Execute-Debug..

This seems to be never ending cycle for any developer. Considerable amount of time of this cycle is spend in Debug phase, wherein user steps through breakpoints and traverse the objects and their properties.

Thankfully, Microsoft has ensured that primitive types always shows the value, instead of any less-meaningful information.

Image

But what happens when you attempt to hover over instance of a user-defined class ? The pop-up shows the type of class.

Image(1)

Waiting for the pop-up to appear and then using the ‘+’ to traverse the object to see its properties can be a cumbersome task, especially when you are ‘mostly’ interested in one or two properties. Many a times, you would pull you could control what the debugger displays.

This is where DebuggerDisplay  attribute comes into play. Of course, you could always use ‘ToString()’ for the same purpose, but lets say, ‘ToString()’ should be reserved for more meaningful jobs.

All you need to do is to decorate the class with DebuggerDisplay Attribute, pass a string with property name from the class (within curly braces) and you are all set to have debugger tool-tips of your choice.

For example, in my example Class Student, I have different properties like FirstName, LastName, Age among others. But mostly, I am only interested to know the full name of the student while debugging. As you can see from the example below, I have decorated the class with DebuggerDisplay attribute, and passed an expression ( Yes – You heard it right, you can use expression as well) consisting of a combination of FirstName and LastName.

Image(2)

Voila !! That’s at it. Check what happens now when you debug.

Image(3)

Simple, but interesting isn’t it ?.