Click here to Skip to main content
15,891,864 members
Articles / Desktop Programming / WPF
Tip/Trick

Fighting databinding issues

Rate me:
Please Sign up or sign in to vote.
4.45/5 (6 votes)
15 Jan 2014CPOL3 min read 19.5K   9   4
How to troubleshoot data binding

Introduction

We all know that DataBinding is one of the most powerful concepts of WPF. So, today I thought of writing something on how to troubleshoot data binding related issues while working with any XAML based application. Here I'll not talk about what and how data binding works, instead I'll jump directly on the relevant part. So, let's start by picking up the troubleshooting methods which can make a developer's work bit easy.

Way 1: Using Visual Studio Output Window

Visual Studio provides high level information about binding which is sufficient to resolve very small problems like name mismatch, etc. Let's understand this along with a code snippet:

XML
<Grid>
       <TextBlock Text="{Binding  ElementName=label, Path=Hello, Mode=OneWay}"/>
       <Label Content="Welcome" Name="label"/>
 </Grid>

Now open your output window and press F5, the application will launch. In output window, you will notice the message stating:

System.Windows.Data Error: 40 : BindingExpression path error: 'Hello' property not found on 'object' ''Label' (Name='label')'. BindingExpression:Path=Hello; DataItem='Label' (Name='label'); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

After reading the above message, it is very easy to identify and resolve the issue. Isn't it ???

Way 2: Using TraceLevel

TraceLevel is an AttachedProperty which was introduced with .NET 3.5. This adds the trace information to the output window of Visual Studio with a detail level of None, Medium, or High. To use this TraceLevel property, one extra namespace needs to be incorporated in XAML as:

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

and add the TraceLevel to the binding as:

XML
<Grid>
    <TextBlock Text="{Binding  ElementName=label, Path=Hello, Mode=OneWay,diag:PresentationTraceSources.TraceLevel=High}"/>
        <Label Content="Welcome" Name="label"/>
</Grid> 

Way 3: Using snoop

Snoop is the WPF utility which allows you to browse through the visual tree of a running WPF application. More details about snoop can be found here.

Way 4: Debugging Data Binding Using a Converter

We can write a converter and put a breakpoint inside the convert method. Once this is done, the converter needs to be setup in the binding. Let's have a look at the code:

C#
namespace DebuggingDataBinding
{
    /// <summary>
    /// Converter to debug the binding values
    /// </summary>
    public class DebugConvertor : IValueConverter
    {
        #region IValueConverter Members

        /// <summary>
        /// ask the debugger to break
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object Convert(object value, Type targetType, 
        	object parameter, System.Globalization.CultureInfo culture)
        {
            Debugger.Break();
            return Binding.DoNothing;
        }

        /// <summary>
        /// ask the debugger to break
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object ConvertBack(object value, Type targetType, 
        	object parameter, System.Globalization.CultureInfo culture)
        {
            Debugger.Break();
            return Binding.DoNothing;
        }

        #endregion
    }

    /// <summary>
    /// Markup extension to debug databinding
    /// </summary>
    public class DebugBindingExtension : MarkupExtension
    {
        /// <summary>
        /// Creates a new instance of the Convertor for debugging
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <returns>Return a convertor that can be 
        /// debugged to see the values for the binding</returns>
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return new DebugConvertor();
        }
    }
} 

In the above snippet, provide value will create an instance of converter and return it. Now the XAML binding to use this extension will be as:

XML
<Window x:Class="DebuggingDataBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DebuggingDataBinding"
    Title="Window1" Height="300" Width="300">
        <Grid Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Height, Converter={local:DebugBinding}}"/>
</Window>

Way 5: Using ExceptionValidationRule

One can associate ValidationRules with binding objects. So, whenever exception is thrown while updating binding source property, ExceptionValidationRule class will take care of it based on how we specify our logic to react with these exceptions. Let's have a look at the code.

I have a class named Person as:

C#
public class Person
{
    private string firstname;
    public string Firstame
    {
        get { return this.firstname; }
        set
        {
            if (string.IsNullOrEmpty(value))
            {
                throw new Exception("First name cannot be null or empty");
            }
            this.firstname = value;
        }
    }
} 

Now we need to associate a rule with the binding and that can be done using in-built class called ExceptionValidationRule and XAML code will be:

XML
<TextBox Height="30" Width="80">
    <TextBox.Text>
        <Binding Path="FirstName" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <ExceptionValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Please note, one can always come up with their own validation rules.

Bit on Performance

  • Less converters can lead to good performance - If possible, use minimal converters because converters require boxing and unboxing. One alternative is to create a property in a ViewModel, do conversion related activity in getter and bind to it.
  • Binding.DoNothing - This seems to be useful in the scenario where return value of a converter need not interfere in the binding process. In such cases, FallbackValue can be used.
  • Data binding cheatsheet can be found here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
BugMinor type Pin
_Noctis_3-Jan-14 17:46
professional_Noctis_3-Jan-14 17:46 
GeneralRe: Minor type Pin
Shweta Lodha16-Jan-14 10:03
Shweta Lodha16-Jan-14 10:03 
GeneralRe: Minor type Pin
_Noctis_16-Jan-14 11:57
professional_Noctis_16-Jan-14 11:57 
GeneralMy vote of 3 Pin
netizenk3-Jan-14 7:26
professionalnetizenk3-Jan-14 7:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.