Colin Eberhardt's Adventures in WPF

The mini-ViewModel pattern

August 7th, 2009

The construction of a ViewModel is often seen as the standard technique for solving binding problems within WPF and Silverlight. However, the addition of a ViewModel adds complexity to your code. This post describes an alternative method where a mini-ViewModel is applied directly to the problem areas in the view, leaving the rest to use simpler, straightforward binding to business objects.

One of the features of WPF / Silverlight that appealed to me immediately when I started to learn it was the flexibility of the binding framework. The concepts of DataContext inheritence and flexibility of the value converters results in a lot less glue-code, which makes me a happy developer! However, it does not take long before you start finding examples that just dont fit with the framework and things start to get just little more complex. This blog post describes one such example.

The example used in this blog post is of a very simple application which displays a business card. The business object rendered by the application, ContactDetails, has a number of simple CLR properties. Constructing a UI for viewing this business object is very easy, simply create an instance of this object (in a real application this object might come from a database or web service) and set it as the DataContext of the view:

public Page()
{
    InitializeComponent();
 
    ContactDetails details = new ContactDetails()
    {
        Company = "Scott Logic Ltd.",
        Email = "ceberhardt@scottlogic.co.uk",
        URL = "http://www.scottlogic.co.uk",
        Country = "UK",
        FullName = "Colin Eberhardt",
        PhoneNumber = 4408452241930
    };
 
    this.DataContext = details;
}

We then create some simple XAML with UI elements that bind to the various propeties of our object …

<Grid x:Name="LayoutRoot" Background="White">
    <Border BorderBrush="LightGray" Background="White"  BorderThickness="1.5" CornerRadius="20"
        VerticalAlignment="Center" HorizontalAlignment="Center">
        <Border Margin="5" BorderBrush="LightGray" BorderThickness="1.5" CornerRadius="15">
            <Border.Background>
                <ImageBrush>
                    <ImageBrush.ImageSource>
                        <BitmapImage UriSource="back.jpg" />
                    </ImageBrush.ImageSource>
                </ImageBrush>
            </Border.Background>
 
            <StackPanel Orientation="Vertical" Margin="10">
                <TextBlock Text="{Binding FullName}"
                           FontSize="15"
                           FontWeight="Bold" />
                <Rectangle Stroke="DarkGray" HorizontalAlignment="Stretch"
                           StrokeThickness="0.5" Height="1"/>
                <TextBlock Text="{Binding Company}" Margin="0,10,0,0"/>
                <StackPanel Orientation="Horizontal" >
                    <TextBlock Text="e: "/>
                    <TextBlock Text="{Binding Email}" />
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="w: "/>
                    <HyperlinkButton Content="{Binding URL}"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="p: "/>
                    <TextBlock Text="{Binding PhoneNumber}"/>
                </StackPanel>
            </StackPanel>
        </Border>
    </Border>
</Grid>

And we get a lovely looking business card:

card

One problem with the above example is the phone number, outputting the raw number ‘4408452241930′ is not terribly readable, besides phone numbers have a standard format, in this case, the phone number would be represented as ‘+44 (0)845 2241930′. Also, let’s make the problem more interesting; you might want to highlight the international dialing code in a different colour, or, if the application is being used by a UK client, display the number in a local format without the international code ‘0845 2241930′. So just how do we achieve this?

In order to break the number up into different blocks of text, with different colours (i.e. styles), we need to modify our view to have multiple TextBlocks mapped to the PhoneNumber property of our business object. The part of our view which renders the phone number is modified as follows:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="p: "/>
    <TextBlock Text="... country code ..." Foreground="LightGray"/>
    <TextBlock Text="... area code ..."/>
    <TextBlock Text="... local number ..."/>
</StackPanel>

But just how exactly do we bind the properties of these business objects?

One approach would be to use a value converter for each binding in order to extract the required part of the number, for example a CountryCodeValueConverter could be implemented which grabs the first 2 digits of the number. However, this approach is a little inelligent in that it fragments our logic into a number of separate classes, furthermore, if we want country specific formatting this requires the use of multibindings, which can be rather cumbersome if over-used (for a Silverlight implementation of multi bindings see my blog post from earlier this year).

Another approach which is often used to tackle tricky binding problems is the use of the Model-View-ViewModel (MVVM) pattern. With this pattern, our ContactDetails object is the Model, we construct a ViewModel which is a UI-oriented abstraction of the Model and it is this which we bind to the View. WPF guru Josh Smith describes MVVM as “a value converter on steroids” in order to highlight the usefulness of the pattern in this context.

The basic approach used here is to bind your View to a ViewModel rather than binding it to the business object directly. The ViewModel is specific to the view and wraps the business object (i.e. Model), forwarding the property values and change notification to the View. This extra layer allows us to supplement the properties of the Model object, adding new computed properties which are specific to the View. In this case, these computed properties can be used to expose ‘country code’, ‘area code’, etc… to our View.

(This is a common pattern so I am not going to reproduce the code required here, however, if you are interested, the attached sourcecode accompanying this article contains a regular ViewModel version as well as a mini-ViewModel implementation)

Whilst this approach works, my issue with it is that it adds quite a bit of boiler-plate code for wrapping properties, forwarding events etc … The removal of this glue-code is the exact reason that I like WPF/Silverlight so much! The MVVM pattern is primarily for supporting the designer-developer paradigm and enabling unit testing of UI applications, in my opinion the use of MVVM for anything else is just plain wrong!

So, how can we solve the problem of providing a nicely formatted phone number without the pain of bashing out line-after-line line of boiler-plate MVVM code? My solution to the problem isn’t to dispose of the MVVM pattern altogether, rather, it is to localise its usage to just the problem area. The first step is to encapsulate the rendering of the phone number as a user control:

...
<StackPanel Orientation="Horizontal">
    <TextBlock Text="p: "/>
    <local:PhoneNumberControl Number="{Binding PhoneNumber}" />
</StackPanel>
...

… which probably makes sense anyway from a perspective of good design and code re-use!

Now that we have moved the phone number property within the PhoneNumberControl we have isolated the problem and can deal with it locally. We can create a PhoneNumberControlViewModel which splits the phone number up into its various components and bind this to the PhoneNumberControl.

The control’s ViewModel looks something like this:

public class PhoneNumberControlViewModel : INotifyPropertyChanged
{
    public PhoneNumberControlViewModel(PhoneNumberControl ctrl)
    {
        _ctrl = ctrl;
        ComputeProperties();
 
        // listen to property changes in the control (we are interested
        // in just the Number property)
        _ctrl.PropertyChanged += Control_PropertyChanged;
    }
 
    private PhoneNumberControl _ctrl;
 
    private string _countryCodeText;
 
    private string _areaCodeText;
 
    private string _localNumberText;
 
    public string CountryCodeText
    {
        get { return _countryCodeText; }
        set { _countryCodeText = value; OnPropertyChanged("CountryCodeText");  }
    }
 
    public string AreaCodeText
    {
        get { return _areaCodeText; }
        set { _areaCodeText = value; OnPropertyChanged("AreaCodeText"); }
    }
 
    public string LocalNumberText
    {
        get { return _localNumberText; }
        set { _localNumberText = value; OnPropertyChanged("LocalNumberText"); }
    }
 
    private void Control_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Number" || e.PropertyName == "Country")
        {
            ComputeProperties();
        }
    }
 
    private void ComputeProperties()
    {
        string formattedNumber = _ctrl.Number.ToString();           
        CountryCodeText = "+" + formattedNumber.Substring(0, 2);
        AreaCodeText = " (" + formattedNumber.Substring(2, 1) + ")" + formattedNumber.Substring(3, 3);
        LocalNumberText = " " + formattedNumber.Substring(6);
    }
}

Note that here the ViewModel is ‘wrapping’ the PhoneNumberControl rather than an instance of some Business / Model object.

Now we just set our ViewModel as the DataContext for the View, as per the typical usage of this pattern:

public PhoneNumberControl()
{
    InitializeComponent();
 
    this.DataContext = new PhoneNumberControlViewModel(this);
}

… and it doesn’t work. If you try the above, you will find that the binding on the PhoneNumberControls Number property no longer works. So why is this? if you look back at where the PhoneNumberControl instance is defined in our business card’s XAML markup you see that its Number property is bound as follows:

<local:PhoneNumberControl Number="{Binding PhoneNumber}" />

The source of this binding is not explicitly set, so will default to using the DataContext of the PhoneNumberControl instance. However, we have just changed this DataContext in our constructor to something else … oops!

Solving this problem is actually quite simple, the PhoneNumberControl markup is as follows:

<UserControl x:Class="SLMiniViewModel.PhoneNumberControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot" Orientation="Horizontal">
        <TextBlock Text="{Binding CountryCodeText}" Foreground="DarkGray"/>
        <TextBlock Text="{Binding AreaCodeText}"/>
        <TextBlock Text="{Binding LocalNumberText}"/>
    </StackPanel>
</UserControl>

If we modify our binding to the ViewModel as follows:

public PhoneNumberControl()
{
    InitializeComponent();
 
    LayoutRoot.DataContext = new PhoneNumberControlViewModel(this);
}

The subtle difference being that the ViewModel is now bound to the StackPanel which is the root of our visual tree within the control. This means that the PhoneNumberControl DataContext is still inherited from the business card and is our business object instance, the DataContext switch to the ViewModel is now neatly tucked just within the PhoneNumberControls visual tree, and it is this DataContext which our TextBlocks will inherit and bind to.

The result is that we can now use our mini-ViewModel embedded within the PhoneNumberControl to expose properties which are more amenable to binding to our View:

card2

Whilst this is a quite trivial example, in real-world applications, more complex examples where the data representation within the View is dependant on a number of properties are quite common. The source code accompanying this article extends the example a little further by making the formatting dependant on a second property of the business object. This is the sort of problem that would either push you towards multi-binding and numerous fragmented value converters, or a ViewModel.

In conclusion, the use of a mini-ViewModel which is embedded within a UserControl allows you to solve tricky binding problems without being weighed down by rolling out the MVVM pattern across your entire View. I am not against the MVVM pattern in itself, however I do firmly believe that it should only be used to solve the problems which it is was specifically designed for, i.e. supporting the designer-developer workflow and unit testing.

You can download the source-code for this article: SLMiniViewModel.zip – this project contains both MVVM and mini-MVVM implementations (count the number of lines in the ViewModel and contrast it with the mini-ViewModel).

Regards, Colin E.

Exposing Bindings as Properties of a Control

June 19th, 2009

card

I must admit that the title of this post is not entirely clear, however I couldn’t find a way to sum up the content in one short sentence, so we’ll dive straight into an example. Let’s say for example you have developed a funky little business-card as illustrated above, using the simple XAML below:

<Border BorderBrush="LightGray" Background="White"  BorderThickness="1.5" CornerRadius="20"
        Width="220" Height="120">
    <Border Margin="5" BorderBrush="LightGray" BorderThickness="1.5" CornerRadius="15">
        <Border.Background>
            <ImageBrush>
                <ImageBrush.ImageSource>
                    <BitmapImage UriSource="back.jpg" />
                </ImageBrush.ImageSource>
            </ImageBrush>
        </Border.Background>
 
        <StackPanel Orientation="Vertical" Margin="10">
            <TextBlock Text="{Binding Name}"
                       FontSize="15" FontWeight="Bold" />
            <Rectangle Stroke="DarkGray" HorizontalAlignment="Stretch"
                       StrokeThickness="0.5" Fill="Black" Height="1"/>
            <TextBlock Margin="0,10,0,0"  Text="{Binding Company}"/>
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="e: " FontSize="10"/>
                <TextBlock Text="{Binding Email}" FontSize="10"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="w: " FontSize="10"/>
                <HyperlinkButton Content="{Binding Web}" FontSize="10"
                             NavigateUri="{Binding Web}"/>
            </StackPanel>
        </StackPanel>
    </Border>
</Border>

The above XAML creates a simple visual layout that binds to the Name, Email, Web and Company properties of the data object which is presented to the inherited DataContext. Nice and simple.

Now, let’s say you want to re-use this XAML markup in a number of places across your application. The obvious solution is to package it within a UserControl. However, elsewhere within the application contact details are stored in different types, with different properties, perhaps the property Web is used in some places, whereas the property URL is used elsewhere. If our UserControl simply contains the XAML markup given above, the binding paths are hard-coded and inflexible. So, how do we package the above markup for re-use whilst maintaining flexibility?

In UI frameworks which do not support databinding the obvious choice would be to define an interface IContactDetails, which defines a compile-time contract that clients of the control must implement on their business objects. This would allow us to enforce the presence of properties with specific names. However, with WPF / Silverlight the binding framework removes the need for controls to demand the presence of a certain interface and life is now much better as a result!

So … what we really want here is to allow the clients of our ContactDetails user control to provide bindings for the various framework elements within the user control itself.

Bindings can be constructed in code-behind by invoking the SetBinding method defined on DependencyObject as show in the example below:

// create a binding with a given source and property-path
Binding binding = new Binding();
binding.Source = myClass;
binding.Path = new PropertyPath("WindowTitle");
// bind the button's Content property
button.SetBinding(Button.ContentProperty, binding);

Therefore, if we were to expose the various Bindings as properties of the control (hence this blog post’s title), we could set the name, email, web elements binding accordingly using the Setbinding method.

The first time I tried this I added a NameBinding dependency property of type Binding to my UserControl, so that the client XAML looked as follows:

<local:ContactDetailsControl
    NameBinding="{Binding Name}"/>

However, this didn’t quite have the desired effect. When the XAML reader processes the above markup it creates the Binding object that we are after, however it does not set the NameBinding property value to this binding. Instead, it uses it to bind the NameBinding property.

The solution to the problem is to make NameBinding a standard CLR property. This time when the XAML reader encounters the above markup it once again creates the Binding object, but since NameBinding is not a dependency property it does not use it to bind the property, it simply sets the property value.

The code-behind of our ContactDetails user control looks like this:

public partial class ContactDetailsControl : UserControl
{
    public Binding NameBinding { get; set; }
    public Binding CompanyBinding { get; set; }
    public Binding WebBinding { get; set; }
    public Binding EmailBinding { get; set; }
 
    public ContactDetailsControl()
    {
        InitializeComponent();
    }
 
    private void Border_Loaded(object sender, RoutedEventArgs e)
    {
        nameText.SetBinding(TextBlock.TextProperty, NameBinding);
        webText.SetBinding(HyperlinkButton.ContentProperty, WebBinding);
        webText.SetBinding(HyperlinkButton.NavigateUriProperty, WebBinding);
        companyText.SetBinding(TextBlock.TextProperty, CompanyBinding);
        emailText.SetBinding(TextBlock.TextProperty, EmailBinding);
    }
}

The four bindings are exposed as CLR properties. When the UI is Loaded, we use them to bind the various elements within the control. The net result is that we now have a re-useable control whilst maintaining the flexibility provided by the binding framework, as illustrated by its usage below:

<local:ContactDetailsControl
    NameBinding="{Binding FullName}"
    WebBinding="{Binding Website}"
    CompanyBinding="{Binding Company}"
    EmailBinding="{Binding Email}"/>

Now for another example and a bit more fun …

The above Silverlight application shows a number of particles exhibiting Brownian motion.

This application creates 50 instances of a Particle object within an ObservableCollection:

class Particle : INotifyPropertyChanged
{
    public double XLocation { ... }
    public double YLocation { ... }
    public double Excitement { ... }
}

The particles are rendered by a ScatterControl, which is a UserControl:

<Border BorderBrush="LightGray" BorderThickness="1">
    <!-- ItemsSource property set in code-behind -->
    <local:ScatterControl x:Name="scatterControl"
                      XValueBinding="{Binding Path=XLocation}"
                      YValueBinding="{Binding Path=YLocation}"
                      FillBinding="{Binding Path=Excitement,
                            Converter={StaticResource FillConverter}}"/>
</Border>

This control has an ItemsSource property of type IEnumerable, and exposes three other properties of type Binding.

The markup for this control is given below:

<UserControl ... >
 
    <ItemsControl x:Name="itemsControl">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Canvas>
                    <Ellipse Width="10" Height="10" Fill="Red"
                             Loaded="Ellipse_Loaded"/>
                </Canvas>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>    
</UserControl>

The particles are rendered using an ItemsControl, which creates an instance of an Ellipse for each bound particle and places it within a Canvas (As defined by the ItemsControl.ItemsPanel property). As each ellipse is loaded, we set the bindings in code-behind:

private void Ellipse_Loaded(object sender, RoutedEventArgs e)
{
    Ellipse ellipse = sender as Ellipse;
    ellipse.SetBinding(Canvas.LeftProperty, XValueBinding);
    ellipse.SetBinding(Canvas.TopProperty, YValueBinding);
    ellipse.SetBinding(Ellipse.FillProperty, FillBinding);
}

Again, by exposing Bindings as properties this user control is just as flexible as if its markup was included in the page directly. This example also illustrates another interesting point, the Bindings that the client provided have been re-used for each Ellipse that was created by the ItemsControl. This is made possible because when SetBinding is invoked on our Ellipse, the Binding is not associated with the Ellipse, rather, it is used to create an instance of a BindingExpression. Binding is used to declare a binding, whereas BindingExpression is the implementation, i.e. it does the heavy-lifting of copying data to-and-from from source to target (and vice-versa).

You can download the full source for both examples: bindingproperties.zip

Regards, Colin E.

Dependency Property Performance and Lissajous Figures

June 2nd, 2009

A few night ago I was working on a Siverlight control which renders some quite complex Paths, the geometry of which is determined from a number of dependency properties. In order to gain UI coolness points I wanted to animate the dependency properties in order to see a smooth transition of the Path geometry between the old and new values. The animation itself was easy to implement, but the resultant animation was distinctly choppy.

Now, I cannot share the code of the Silverlight control I was working on, so I have decided to illustrate the point via a Lissajous Figure. These curves are plotted using the following simple formula:

A simple Lissajous Figure can be constructed by creating a UserControl which dependency properties for the various parameters in the above equations. The control contains a single path whose Data property will be set to a suitable geometry in code behind, and a ‘container’ element for our path which we use to determine the width / height of our curve.

<UserControl ...>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="PathContainer" Margin="5">            
            <Path x:Name="lissajousFigure" Stroke="#9EFFFF" StrokeThickness="1"/>
        </Grid>
    </Grid>
</UserControl>

The points that are used to construct the geometry are calculated from the ActualXFrequency, ActualYFrequency, ActualPhase properties of our user control, together with the ActualWidth and ActualHeight of the container in order to scale the curve appropriately.

for(double t = 0; t < Math.PI * 10; t += Math.PI / 36)
{
    points.Add(new Point()
    {
        X = PathContainer.ActualWidth * Math.Sin(t * ActualXFrequency) / 2
            + ActualWidth / 2,
        Y = PathContainer.ActualHeight * Math.Cos(t * ActualYFrequency + ActualPhase) / 2
            + PathContainer.ActualHeight / 2
    });
}

When I investigating the choppy animation performance in my Silverlight control I concentrated initially on other parts of the application; the construction of the paths, the property changed events and the resultant chain reaction of event which can result in a spiders-web of method invocations. It was not until a little later that I focussed on the code that constructed the geometry, which looks not too dissimilar to the above.

At first sight, the code looks just fine, we are performing a number of simple operations on a few simple properties. However, this is not the case, these properties are not simple CLR properties backed by value or reference types. These are Dependency Properties, which are much more complex beasts!

A quick change to the above code to ensure that the DP accessors are called only once, rather than 360 times, resulted in code which ran ~400 times faster!

double actualWidth = PathContainer.ActualWidth;
double actualHeight = PathContainer.ActualHeight;
double actualXFrequency = ActualXFrequency;
double actualPhase = ActualPhase;
double actualYFrequency = ActualYFrequency;
 
for(double t = 0; t < Math.PI * 10; t += Math.PI / 36)
{
    points.Add(new Point()
    {
        X = actualWidth * Math.Sin(t * actualXFrequency) / 2
            + actualWidth / 2,
        Y = actualHeight * Math.Cos(t * actualYFrequency + actualPhase) / 2
            + actualHeight / 2
    });
}

When you think about the features that the DP framework provides (databinding, animation, inheritance etc …), it is not at all surprising that this is at some performance cost. And I will forgive the reader if they tell me that I am stating the obvious! However, in code behind, where DPs are accessed via their CLR wrappers it is easy to forget this. It should also be noted that DPs are far from slow. It is only when they are used as part of a complex iterative calculations that the performance-hit will be felt.

Anyhow, this is a small lesson in what is possibly obvious! However, I must admit, I had far too much fun creating the Lissajous Figure example application as you can see from the app. at the start of this article … it takes me back to Physics lab at University!

A few other points of interest:

  • The code uses ElementName binding attached behaviour I created in an earlier blog post. As a result, there is no code-behind in the main page (I may be flirting with Silverlight but my WPF credibility remains intact!)
  • The various dependency properties for the Lissajous Figure user control are defined using T4 templates as described in this codeproject article.

I also really like the way that when one of the DPs such as Phase is updated, a storyboard is used to animate the accompanying ActualPhase DP to the updated value.

partial void OnPhasePropertyChanged(DependencyPropertyChangedEventArgs e)
{
    AnimateProperty("ActualPhase", Phase, 100);
}
 
private void AnimateProperty(string propertyName, double targetValue, int milliseconds)
{
    Storyboard sb = new Storyboard();
 
    DoubleAnimation b = new DoubleAnimation() { To = targetValue };
    b.Duration = new Duration(new TimeSpan(0, 0, 0, 0, milliseconds));
    sb.Children.Add(b);
    Storyboard.SetTarget(b, this);
    Storyboard.SetTargetProperty(b, new PropertyPath("(" + propertyName + ")"));
 
    sb.Begin();
}

This means that even though the slider controls bound to the DPs move in discrete steps, the above animation gives the illusion of the steps being continuous.

You can download the full project source here: silverlightdpperformance.zip.

[Oscilloscope image reproduced from Wikipedia under Creative Commons Licence]

Regards, Colin E.

Binding a Silverlight DataGrid to dynamic data Part 2 – editable data and INotifyPropertyChanged

April 22nd, 2009

In my previous blog post I described a method for solving the commonly faced problem of binding a Silverlight DataGrid to dynamic data, the form of which is not know at compile time. This blog post extends on the method previously described, adding change notification, allowing the DataGrid to synchronise the UI with changes to the bound data and to allow the user to edit the DataGrid’s contents.

To briefly recap my previous post, the dynamic data is copied to a collection of Rows:

public class Row
{
  private Dictionary<string, object> _data = new Dictionary<string, object>();
 
  public object this [string index]
  {
    get { return _data[index]; }
    set { _data[index] = value; }
  }
}

Where the row ‘properties’ which are implemented via the string indexer bound to the grid via a ValueConverter. The XAML for the DataGrid looks like the following:

<data:DataGrid Name="_dataGrid" AutoGenerateColumns="False"  IsReadOnly="False" Margin="5">
    <data:DataGrid.Columns>
        <data:DataGridTextColumn Header="Forename"
                                 Binding="{Binding Converter={StaticResource RowIndexConverter},
                                    ConverterParameter=Forename}"/>
        <data:DataGridTextColumn Header="Surname" 
                                 Binding="{Binding Converter={StaticResource RowIndexConverter},
                                    ConverterParameter=Surname}"/>
        ...               
    </data:DataGrid.Columns>
</data:DataGrid>

Where the ValueConverter takes the ConverterParameter and uses it to index the bound Row instance:

public class RowIndexConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    Row row = value as Row;
    string index = parameter as string;
    return row[index];
  } 
}

It is important to note that the Binding does not have a Path defined. As a result, the binding source is the Row instance itself rather than a property of the Row as would more normally be the case when binding data. The rest of the post described how to create a collection view which sorts the collection via the Row’s string indexer. You can read about this in full in my previous blog post.

Now, one question a few people have asked me is how to implement INotifyPropertyChanged on the Row class in order to make the DataGrid editable. Simply implementing INotifyPropertyChanged on the Row class, with events raised from the index setter, will not make the grid editable or synchronised with the bound data. The underlying problem here is that the Binding does not have a Path specified, therefore, the binding framework does not know which property name to look out for when handling PropertyChanged events. Interestingly I would expect the above bindings to be updated if a PropertyChanged event were raised with a null or empty PropertyName string, however they do not.

So if the Binding framework needs a Path for the binding in order for change notification to work, we will have to fabricate one for this purpose! We can modify the Row class as follows, adding a Data property which is simply a reference to the Row instance itself:

public class Row : INotifyPropertyChanged
{
    private Dictionary<string, object> _data = new Dictionary<string, object>();
 
    public object this [string index]
    {
        get
        {
            return _data[index];
        }
        set
        {
            _data[index] = value;
 
            OnPropertyChanged("Data");
        }
    }
 
    public object Data
    {
        get
        {
            return this;
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void OnPropertyChanged(string property)
    {
        if (PropertyChanged!=null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

In order to bind this class we modify our bindings so that the source Path points to the Data property:

...
<data:DataGridTextColumn Header="Forename"
                           Binding="{Binding Path=Data, Converter={StaticResource RowIndexConverter},
                           ConverterParameter=Forename}"/>
<data:DataGridTextColumn Header="Forename"
                           Binding="{Binding Path=Data, Converter={StaticResource RowIndexConverter},
                           ConverterParameter=Surname}"/>
...

With this change in place, all of our bindings are bound to the Row’s Data property. Again, the Row’s indexer is being accessed via our value converter. However, if any ‘property’ change via the string indexer setter will result in all of our bindings being updated for that Row. I know, it is not the most efficient solution – but at least it work!

The next problem is making the DataGrid editable. The problem we face here is that all of our bindings are to the same property, Data. When a cell is edited, the binding framework will quite happily call the Data properties setter, with the updated value. However, how do we know which property of the Row was really being set? The only place we hold this information is in the ConverterParameter which is fed to our RowIndexConverter value converter. Fortunately, there is a solution to this problem, when the binding framework updates the bound object, it will first invoke the ConvertBack method on our value converter. This gives us the opportunity to ‘capture’ the converter parameter and feed it into the setter of our Data property, as shown below:

public class RowIndexConverter : IValueConverter
{
    ...
 
    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return new PropertyValueChange(parameter as string, value);
    }
}

Where PropertyValueChanged is a simple value object:

public class PropertyValueChange
{
    private string _propertyName;
    private object _value;
 
    public object Value
    {
        get { return _value; }
    }
 
    public string PropertyName
    {
        get { return _propertyName; }
    }
 
    public PropertyValueChange(string propertyName, object value)
    {
        _propertyName = propertyName;
        _value = value;
    }
}

The setter for the Data property will now be invoked with an instance of PropertyValueChanged, giving it all the information it requires to invoke the string indexer with the correct ‘property’ name:

public class Row : INotifyPropertyChanged
{
    ...
 
    public object Data
    {
        get { return this; }
        set
        {
            PropertyValueChange setter = value as PropertyValueChange;
            _data[setter.PropertyName] = setter.Value;
        }
    }
    ...
}

With this change in place, we the user is able to edit the data bound to the DataGrid, and the binding ensures that the DataGrid UI is synchronised with any changes to the bound data that may happen elsewhere in our code.

One final thought that struck me is that this technique uses the Binding’s associated ValueConverter to access the Row’s string indexer, but what if we wanted to use a ValueConverter for something else like formatting? Fortunately it is a pretty straightforward process to nest one value converter inside another. For details, see the attached project. For now, have quick play with the grid below, where all the columns are editable and the button click event sets the Row’s Age property demonstrating how the DataGrid is synchronised:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // demonstrate the property changes from code-behind still work.
    Random rand = new Random();
    foreach (var row in _rows)
    {
        row["Age"] = rand.Next(10) + 5;
    }
}

Also, the Age column has a value converter associated …

So there you have it, binding to dynamic data with INotifyPropertyChanged implemented and an editable DataGrid. The only reservation I have with this technique is that I am really bending the binding framework to achieve the results, having a Data property which expects different types for the getter and setter is a little ugly … use with caution!

You can download the project sourcecode: silverlightdynamicbinding2.zip

Regards, Colin E.