Jan 28, 2008

How to debug WPF bindings

45DebuggingDataBinding

Data Binding can be tricky to debug. In this post, I will share the techniques I use to debug WPF bindings, including the new debugging improvements we implemented in the latest 3.5 release. I will discuss the following four techniques:

  • Scanning Visual Studio’s Output window for errors.
  • Using Trace Sources for maximum control.
  • Using the new property introduced in WPF 3.5 – PresentationTraceSources.TraceLevel.
  • Adding a breakpoint to a Converter.

The DataContext of this app is set to a new instance of Star, which is a class that contains two properties: Picture and Caption. Picture is of type BitmapImage and contains an image of the sun, which I included in the project. Caption is a string property that takes a while to be initialized (more details about this later).


Output Window

In the XAML of this application, I have an Image whose Source is data bound to an incorrect property name. This is a simple scenario that causes a Binding to fail.

    <Image Source="{Binding Path=PictureWrong}" Width="300" Height="300" Grid.Row="0"/>

Every time a Binding fails, the binding engine prints an informative message in the Output window of Visual Studio. In this case, I get the following message:

    System.Windows.Data Error: 35 : BindingExpression path error: ‘PictureWrong’ property not found on ‘object’ ”Star’ (HashCode=49535530)’. BindingExpression:Path=PictureWrong; DataItem=’Star’ (HashCode=49535530); target element is ‘Image’ (Name=”); target property is ‘Source’ (type ‘ImageSource’)

This message should give you enough information to quickly figure out the mistake in the property name.

Advantage of this technique:

  • It is very easy to look at the Output window, and in most cases it’s sufficient. It should be the first approach you consider when you have a problem with your bindings.

Disadvantage of this technique:

  • Most real world applications print so much information to the Output window that it may be hard to find the error you’re looking for.


Trace Sources

The Trace Sources solution was already around in WPF 3.0. It adds a lot more flexibility to the previous solution by allowing you to control the level of detail you care about, where you want that messages to be printed and the WPF feature you want to debug.

The Trace Sources solution relies on a config file for the configuration of its behavior – the App.config file. Here is a portion of the contents of that file:

    <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="DebugTrace.txt" />
                …
            </sharedListeners>

            <trace autoflush="true" indentsize="4"></trace>

        </system.diagnostics>
    </configuration>

In this file, I am specifying that:

  • I want only messages generated in the Data subarea to be printed. If you’re trying to debug, for example, animations, you would instead add the area System.Windows.Media.Animation.
  • I want as much information as possible about data binding. This was done by setting the switch to All. Other possible values are Off, Error, Warning. For a complete list, look up SourceLevels in .NET Reflector.
  • I want the messages to be printed to an external file called DebugTrace.txt, instead of the Output Window. This file will be created in the bin\debug folder for the application. If you run this application twice, the messages generated the second time will be appended to the existing messages in this file. If you don’t want this behavior, remember to delete the file before running the app.

Other pre-defined listeners allow printing to the Console (ConsoleTraceListener), or to an external file in XML format (XmlWriterTraceListener).

If you run the application with the settings above, you should find a DebugTrace.txt file in the bin\debug directory. If you open it, you will see the data binding error we saw previously in the Output Window, plus four “Information” messages. These lower-priority messages are printed because I specified in the switch that I want all the information available about the bindings.

If you want to learn more about this topic, I recommend Mike Hillberg’s blog. He wrote the best article I’ve read about Trace Sources, which I use frequently as a reference.

Advantages of this technique:

  • It separates the debug messages you care about from the rest of the information printed in the Output window.
  • This solution may help you debug other areas in WPF, not just binding.
  • You can get lower-priority messages (such as information or warnings) that are not typically printed to the Output window.

Disadvantages of this technique:

  • The text file (or whatever form of output you choose) will contain debug messages about all the bindings in your application. Although this is not as much clutter as the Output window, it may still require some digging for you to find exactly the information you need.
  • It won’t help you in scenarios where your Binding actually succeeds, but you still don’t see what you expect in the UI. The first and second techniques I show here only help in scenarios where the Binding fails.

Before you move on, make sure you correct the Path in the Image’s Source so that these errors won’t interfere with the ones I show next.


Trace Level – new in 3.5

In order to understand this feature, let’s start by uncommenting the first TextBlock in the XAML of this application:

    <TextBlock Text="{Binding Path=Caption}" … />

This TextBlock attempts to bind to Caption, a property whose value is slow to be initialized. In this case, I am simulating a slow data source by adding a Dispatcher timer to the constructor, but in reality this delay could have many different causes. Notice also that I am *not* raising a property changed notification when Caption changes value.

    public string Caption
    {
        private set
        {
            this.caption= value;
            //OnPropertyChanged("Caption");
        }
        get
        {
            return caption;
        }
    }

    public Star()
    {
        this.Picture = new BitmapImage(new Uri("Images\\sun.jpg", UriKind.Relative));
        this.Caption = String.Empty;
        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = new TimeSpan(0, 0, 3);
        timer.Tick += new EventHandler(Timer_Tick);
        timer.Start();
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        this.Caption = "Sun";
    }

In this scenario, the Binding will succeed (it will bind to the initial value of empty string), but you don’t see what you expect to see in the UI. The unwanted behavior is caused by the fact that the events happen in an order different from what you expect: the Binding will be evaluated before Caption gets its real value. In this case, there are no errors in the Output window or DebugTrace.txt because the Binding succeeds.

You can use the new debugging feature in 3.5 to debug this scenario by adding the attached property PresentationTraceSources.TraceLevel to the Binding, which can be set to None, Low, Medium and High. Since PresentationTraceSource is not in the default namespace mappings for WPF, you will have to write the following XAML:

    <Window …
    xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    />

    <TextBlock Text="{Binding Path=Caption, diagnostics:PresentationTraceSources.TraceLevel=High}" … />

If you look at the Output window, you will notice that the binding engine generated debug information for every task that may help users find problems with this particular binding:

    System.Windows.Data Warning: 47 : Created BindingExpression (hash=25209742) for Binding (hash=3888474)
    …
    System.Windows.Data Warning: 91 : BindingExpression (hash=25209742): GetValue at level 0 from Star (hash=31609076) using RuntimePropertyInfo(Caption): ‘ ‘
    System.Windows.Data Warning: 71 : BindingExpression (hash=25209742): TransferValue – got raw value ‘ ‘
    System.Windows.Data Warning: 78 : BindingExpression (hash=25209742): TransferValue – using final value ‘ ‘

In this case, we can scan the debug messages quickly to see that there were no errors, and look at the last few messages to understand that the value found at the Source was the empty string. This information will help you come to the conclusion that there is some timing issue with the scenario.

Advantages of this technique:

  • This feature is particularly useful when you know exactly which binding you want to find out more about, which is the most common scenario.
  • It allows you to know more about bindings that succeed, which many times helps you find the mistake in your logic.

Disadvantages of this technique:

  • If you forget to remove the property after you found the problem, it adds to the clutter of the Output Window (which adds to the time it takes to start your application in debug mode).


Converter

The last solution is extremely simple: you can simply add a no-op Converter to your binding and put a breakpoint in its Convert method. This is what this solution looks like:

    <TextBlock Text="{Binding Path=Caption, Converter={StaticResource converter}}" …/>

    public class DebuggingConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value; // Add the breakpoint here!!
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException("This method should never be called");
        }
    }

If you run this code and set a breakpoint inside the Convert method, you can simply hover over the “value” parameter to see what is being passed from the source to the target. In this case, you will see that “value” contains an empty string. This may help you realize that the source of your binding does not have the value you thought it had.

Advantages of this technique:

  • It is really easy to implement. It relies on a concept that most data binding users are familiar with.
  • It does not depend on the Output window.
  • It helps you find out more about scenarios where the binding doesn’t fail.

Disadvantages to this technique:

  • It doesn’t provide as much information as the TraceLevel technique.
  • If the Binding fails early, the Converter may not be called.


Conclusion

I mentioned here techniques to debug WPF bindings using Visual Studio, however there are other tools that can help you with this process. One other tool I use frequently is Snoop, not only to debug bindings but many other aspects of my application. Mole is also useful, and has great documentation.

What technique or tool you use to debug your bindings comes down to a combination of personal preference and your specific scenario.

Here you can find the project with this code built using VS 2008 RTM.

17 Comments
  1. Per Boussard

    Is there any way to understand why I can depend on properties but not any member? I got hurt by this but was able to understand the problem thanks to your debugging hints.

    //P

    • vb

      Thanks for the idea about the no-op converter that is very helpful in times when I am getting the debug output but still can’t seem to track down what is actually going on. Its nice to have another avenue to gather more info. Thanks for writing up this article!

  2. Bea

    Hi Per,

    Do you mean that you would like to data bind to a public field?
    If so, that is a current limitation of WPF’s data binding engine. We only support binding to public properties (and one-way binding to methods). If you really need to bind to a field, you can expose that field as a property through a custom type descriptor. Data binding looks at properties exposed through type descriptors too.

    Conveniently, there is a two-part article on msdn that explains how to expose your fields as properties by using custom type descriptors. Here’s the article:

    Part 1 – http://msdn.microsoft.com/en-us/magazine/cc163816.aspx
    Part 2 – http://msdn.microsoft.com/en-us/magazine/cc163804.aspx

    Once your fields are exposed as properties, you’ll be able to bind to them.

    Hope this helps.

    Bea

  3. Van Nguyen

    How can you handle exceptions thrown on the rendering thread? For example, I have an ItemsControl binded to a list that is populated by a stored procedure that times out.

    • Bea

      Hi Van Nguyen,

      No, it’s not possible to handle exceptions from the rendering thread, but I never came across a scenario that required it. The rendering thread contains native code that is responsible only for the actual rendering of the app, it doesn’t not contain any user code. I never encountered an exception thrown in the rendering thread.

      The scenario you describe is executed on the UI threaad. You should be able to catch exceptions on the UI thread as usual (try/catch).

      Bea

  4. William Garrison

    I found that adding the ValueConverter makes the warnings go away. Is this intentional? Does it happen in all cases, or just mine? Also, is there any way to debug {TemplateBinding} ?

    I used these techniques to try to track down a data binding problem where I get warnings, but the binding actually works. I have over 400 UI elements on the screen and it takes close to 30 seconds when in the debugger, and several seconds just to run (this is not acceptable in our app). I really wasn’t able to make heads-or-tails of the debugging output, so I think I really am onto a data binding bug here.

    If anyone is interested, here is the bug I filed:
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=476990

    • Bea

      Hi William,

      What you describe is a common problem with large applications, and it’s also the reason that lead us to implement PresentationTraceSource. To turn off all data binding warnings to speed up debugging, you can do the following in code:

      PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Off;

      Then, if you want to debug individual bindings, you can use the Converter technique or the Snoop debugging tool.

      I’m not really sure why your warnings go away when you add converters – it’s probably specific to the errors you’re seeing. To debug a TemplateBinding, you can convert it into a Binding with RelativeSource set to TemplatedParent.

      Hope this helps.

      Bea

      • William Garrison

        Thanks for the info Bea.

        Microsoft confirmed that I discovered some WPF 3.5 databinding bugs, but they are already fixed in WPF 4.0. In the example I gave, it not only displays a warning, but tries to create two instances of the object. That explains my performance problem. They also confirmed that they TypeConverter fixes the problem, but they are unsure why. At least I know it is a valid workaround. :-)

        Unrelated: I wish they would stop setting things to “Not Reproducible” for everything. It looks like their system just doesn’t have enough status codes. They reproduced it just fine. They need a status of “Resolved (Fixed in future version)”

        • Bea

          Thanks for reporting the data binding bugs you found.
          Yeah, the bug reporting tool can be a bit limiting at times…

          Bea

  5. Brandon

    Hi, this seems like an incredibly helpful set of recommendations. However, I can’t get the Output window in Visual Studio to display ANY of the messages you’re talking about.

    Could this be because I’m working on an Office plugin (VSTO) with WPF controls embedded in an ElementHost? Or is there something else I’m not enabling?

    I have turned on PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Verbose;

    Brandon

    • Bea

      Hi Brandon,

      There is no special setup for the binding debug messages to appear in the output window – they just show up there. I haven’t tried your scenario, but yes, it’s possible that they don’t come up because you’re using ElementHost. Maybe you can try the trace source or trace level debugging solutions?

      Bea

      • David Bethune

        I should add that I am not doing Office dev. This is a Silverlight 3 project.

    • David Bethune

      Brandon & Bea,

      I have Brandon’s problem! There were some databinding messages from a previous run in my Immediate window, but now NONE get written there. The only diag info shown is the Silverlight loading messages.

      I resent the profile to the General Dev. defaults to make sure I hadn’t kicked something off accidentally…. still no debugging messages at all.

      Help! :-)

      Thanks,
      – D

      • Bea

        Hi David,

        That is strange – it never happened to me. Data binding debugging messages should just show up in the output window, both in WPF and Silverlight.
        You mentioned the “Immediate Window” – please keep in mind that the debug messages show up in the “Output Window”.

        Bea

  6. Pete Maher

    In order to have any data binding exceptions trapped by our application and displayed in our normal error UI I am doing the following at startup:

    WpfTraceListener traceListener = new WpfTraceListener();

    PresentationTraceSources.Refresh();
    PresentationTraceSources.DataBindingSource.Listeners.Add(traceListener);
    PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error;

    and the WpfTraceListener.WriteLine shows the message parameter in our Error dialog.

    I can’t find any documentation to say tell me if this would only be effective in a debug build, presumably not – can anyone confirm?
    And if it is effective regardless of the build then is it going to have a performance impact?
    Also – would a knock on effect of this be that anything less than SourceLevels.Error would not got to any trace listener?

    Basically I feel backed into a corner and want to know if it is reasonable to do what I have done.
    * If I don’t do the above then any exceptions which don’t get noticed during development – either because someone’s eye was not on the Output window or because the exception condition never arose – will not surface in any immediately obvious way during use of the release version of the application.
    * If I include the code above will my application be punished with poorer performance?

    Pete.

    • Bea

      Hi Pete,

      > I can’t find any documentation to say tell me if this would only be effective in a debug build, presumably not – can anyone confirm?
      Tracing is actually not a WPF feature – it was around in .NET before WPF used it. From what I could understand in the MSDN documentation, Trace output happens for both debug and release builds. This should be easy for you to try with your application – is this what you see?
      There may be better ways to avoid debug output from being generated in release builds, but you can always wrap the trace listener code you show above with an #if DEBUG.

      > And if it is effective regardless of the build then is it going to have a performance impact?
      Yes, it will certainly affect performance.

      > Also – would a knock on effect of this be that anything less than SourceLevels.Error would not got to any trace listener?
      That is correct.

      Bea

  7. andy

    thanx dude, veeeery welcome, i’ve spend whole day breaking my poor head ;-) ! god bless u pal, andy

Comments are closed.