Sunday, March 27, 2011

WPF databinding trick (part 1)

The last week, one of my colleague was doing a WPF training session and she ended up having a very strange behavior with the WPF databinding engine. I’ll describe a not well-known behavior of the WPF databinding engine and I’ll try to explain how its works under the scene.

Binding the Text property of a TextBlock to a collection of objects

This is something you’re not supposed to do, but you’ll see it actually works in an unexpected way. In the code-behind of our Window, we have the following C# code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Person person1 = new Person { Age = 45 };
        Person person2 = new Person { Age = 63 };
        Person person3 = new Person { Age = 71 };
        this.DataContext = new List<Person> { person1, person2, person3 };
    }
}
public class Person
{
    public int Age
    {
        get;
        set;
    }
}

The associated XAML looks like the following:
<Window x:Class="WpfApplicationDataContext.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock Margin="10" Text="{Binding Age}"/>
    </StackPanel>
</Window

Here we’re doing something not usual: we’re binding the Text property of the TextBlock (which is of type string) to a collection of objects.

What do you think the Window will display ?

The first time I saw this code, I thought the Window will remain empty. The DataContext is set to a List and we’re trying to find an “Age” property on this collection: THAT CANNOT WORK.
Actually, it does…

What’s happening behind the scene ?

Let’s take a deep breath a take a look at what’s happening behind the scene to make this works.

1. A CollectionView is created
The first thing I was thinking while talking about the problem with my colleague was the use of a collection view. As you probably now, every time you create a binding to a collection property, the engine creates a collection view for you. This view will serve as an intermediate layer between your source and the target to manage selection, filtering and grouping. A good introduction to collection views is available here.
What is important to know is that collection views are shared along same objects instance. It means that when you use the CollectionViewSource.GetDefaultView() method, you’re either creating a default view for the collection (if no one has requested one before) or getting the default view (if it has been created by calling the same method before you).
To make sure I was right about my hypothesis, I added the following code in the C#:

Read more: JAPF