If we're having a problem with a data binding that uses an IValueConverter to convert the data bound value from one type to another, then we can place a breakpoint into the Convert method of the converter. As long as we have correctly set up the converter, we can be sure that the breakpoint will be hit when the binding is evaluated at runtime. If it doesn't get hit, that will mean that we have not set it up correctly.
However, even when we are not already using a converter on a binding that is not displaying the value that we are expecting, we can still add one just for this purpose. We can either add an existing converter to the binding, if we have one of the relevant type, or we can create a simple converter specifically for the purpose of debugging and use that instead. Let's take a look at how we might do this:
[ValueConversion(typeof(object), typeof(object))] public class DebugConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter,
CultureInfo culture) { if (Debugger.IsAttached) Debugger.Break(); return value; } public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture) { if (Debugger.IsAttached) Debugger.Break(); return value; } }
As you can see from the preceding code snippet, it's a very simple implementation of the IValueConverter interface. We start by specifying that we are converting from object to object in the ValueConversion attribute, thereby outlining that we are not actually converting any data bound values in this converter. The rest of the class represents a typical converter class, but without any conversion code.
The only real point of interest here are the two calls to the Debugger.Break method from the System.Diagnostics assembly. When the program execution reaches either of these method calls, it will automatically break, just as if there were breakpoints set on these lines. Therefore, when using this converter, we don't even need to set breakpoints; we can just plug it into the binding, run the program, and investigate the value of the value input parameter.
It can be attached like any other converter:
xmlns:Converters="clr-namespace:CompanyName.ApplicationName.Converters; assembly=CompanyName.ApplicationName.Converters" ... <UserControl.Resources> <Converters:DebugConverter x:Key="Debug" /> </UserControl.Resources> ... <ListBox ItemsSource="{Binding Items, Converter={StaticResource Debug}}" />
However, this method can be unsafe to use in a production environment and the converter should be removed when debugging is finished. If it is left connected in release code, an Exception will be thrown at runtime, complaining that Windows has encountered a user-defined breakpoint. Although I wouldn't recommend leaving a converter that is just used for debugging data bound values connected in a production environment, we can make a slight alteration to it to completely eliminate the danger of this occurring:
[ValueConversion(typeof(object), typeof(object))] public class DebugConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter,
CultureInfo culture) { Break(value); return value; } public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture) { Break(value); return value; }
[Conditional("DEBUG")]
private void Break(object value)
{
Debugger.Break();
}
}
Now, the Debugger.Break method and the data bound value have been moved into a separate Break method, where the value of the value input parameter can be inspected. Note the use of the ConditionalAttribute attribute on this new method. It provides a way to include or exclude methods that it has been set on, depending on the current solution configuration. If the configuration is set to debug, this method can be called, but otherwise, all calls to it are removed from the compiled code. In this way, we can be assured that we will not run into problems with our release code.