So, this was actually a question recently asked by another Bad Monkey getting their feet wet with WPF. The question was: How the hell do you debug data binding issues with WPF in Visual Studio?
I can see how that can be a little frustrating at times. XAML editor in Visual Studio doesn’t exactly offer the same level of “helpfulness” as regular C# editing space. What I mean by that is, that you get rudimentary auto-completion when working with XAML, but not much beyond that. You can go a little further with things like ReSharper but I have actually found that the code analysis that ReSharper does, is often firing false positives especially when it comes to Data Context on various UI Elements. Anyways, let’s talk about what we are actually here for: Data Binding.
If we assume that we are using MVVM pattern and our Data Context should be set to the ViewModel then we should be able to simple set bindings like so:
The above is a simple Items Control that allows us to display a list of UserControls. They are bound to objects stored in a collection called “Sizes” and each item in the collection will take its Data Context from that collection. Pretty straight forward. Now let’s talk about how to spot issues with Bindings. Let’s say that we misspelled the “Sizes” and called it “Sizesss”:
This will still build and offer no feedback that there is no property called “Sizesss” on our ViewModel. You will only find out about it when you actually launch the Window. The console Debug should print something along these lines:
That’s pretty straight forward, and easy to understand. The Debug printouts are our first line of defense here. Here’s a little trick to enhance that print out a little bit:
So we added a property to our Binding that sets the TraceLevel = High. That will result in the same error getting printed out in Console but with a little bit more detail:
Just remember to add the “xmlns:diag=”clr-namespace:System.Diagnostics;assembly=WindowsBase”” to top of your UserControl/Window.
OK, so you might be saying, “that’s great but I am using Visual Studio here, and all I get is Console logs? That’s it? Really?”. Well, you can go a little further and break into code, when there are “any” Binding issues in your project, so that you don’t have to track each binding individually. Assuming this is a Revit project, you can add this code to your OnStartup() method:
You will also need the implementation for the DebugTraceListener() class:
With this in place, every time there is a WPF Binding issue, Visual Studio will break into the Debugger like so:
Now, there is a caveat to this particular method. The issue is Revit itself. Since this method will break on any Binding issues, it means that it will also break on Binding errors that are not part of your app, but let’s say came from Revit itself. Yes, Revit ships with bunch of Bindings broken, so with this method in place, you will have to skip over 5-6 Binding errors just to get Revit to launch. I know, I know…I am not even going to say anything. 🤣
So these two methods should get you all going in the right direction. There are other potential ways of debugging Binding issues. This write up is based on a great post by Mike Woelmer and he lists at least one more in his original post here: Debug
Great tips. Something else I’ve also found useful is FallbackValue property for bindings. This is a value which will be assigned whenever the binding can not be found on runtime. FallbackValue also helps with seeing something in the UI during designtime.
Yeah, the FallbackValue is useful when dealing with things like TextBox or Label to get a good preview of the Control. I don’t think it’s feasible for Collections etc. Still, thanks for the good tip!
Awesome tips, learned some new things! Did you also know about design time data context? You can set that on a window or control to get better intellisence and previews.
That I didn’t know. Thanks! Although I do have to mention that it looks like it only works for parameter-less constructors which I almost never use when working with Revit. My view models are almost always built from some data extracted from Revit DB, which means that I need to tie the two together. I usually do that by passing a Model into the ViewModel via the constructor. I do all my Revit interactions via the Model, but then I can always access it from the ViewModel. In order for the design time data context to work, we need not to pass anything into the constructor. Just something to keep in mind.