Using CLR 4 Dynamics To Mock Bindable Objects in XAML

by Dean 3. February 2010 07:45

When I’m building prototypes in WPF or working on a GUI spike in an agile development team I often find it really unproductive to continuously switch between working in XAML (with my designer hat on), and working on the plumbing code (with my C# hat on).

Wouldn't it be nice to be able to model my data in XAML, and seamlessly use it with XAML Binding expressions that’ll be valid once the ‘real’ data gets plumbed in.

Well, thanks to the dynamic features in CLR v4 this is now a trivial task.

Firstly lets look at the XAML – you’ll quickly see the flexibility in using this approach -

<Window x:Class="DynamicWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <collections:Hashtable x:Key="data">
            <sys:Double x:Key="Prop1">50</sys:Double>
            <sys:String x:Key="Prop2">Hello</sys:String>
        </collections:Hashtable>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <TextBox Text="{Binding Path=Prop2, Mode=TwoWay}" />
        <TextBlock Text="{Binding Path=Prop2}" />
        <Button Content="{Binding Path=Prop1}" Height="{Binding Path=Prop1}" />
    </StackPanel>
</Window>

The critical thing to look at is the resources section (this could be in a separate resource dictionary if you wanted to keep things neat). Basically, I'm creating a hashtable that is going to model the data I anticipate will be available when I hook it all up after the design phase. Essentially, the hashtable keys are the property names of my object, and the hashtable values are the initial values of the properties.

In the example above, I’m expecting my data object to have 2 properties – one called “Prop1”which is a double, and has an initial value of 50, the other is called “Prop2” which is a string, and has an initial value of “Hello”.

Using the above approach, I could model (or mock) just about any simple object I can imagine.

Now we need to turn this hashtable into a real object, and this is where the new DynamicObject class in CLR 4 comes in.

public class DynamicDataObject : DynamicObject, INotifyPropertyChanged
{
    private Hashtable data;
    public event PropertyChangedEventHandler PropertyChanged;
 
    public DynamicDataObject(Hashtable data)
    {
        this.data = data;
    }
 
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = data.ContainsKey(binder.Name) ? data[binder.Name] : null;
        return true;
    }
 
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        data[binder.Name] = value;
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(binder.Name));
        return true;
    }
}

When you inherit from DynamicObject, your object is essentially ‘dynamic’ which means that it’s members are discovered at runtime. In the class above, I'm using the hashtable passed in as the backing data to enable the correct member resolution at runtime. Effectively, this DynamicDataObject class will correctly mock a compiled CLR object with the same member signature.

Now, all we have to do is hook it up with a single line of code in our code-behind file:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new DynamicDataObject((Hashtable)this.Resources["data"]);
    }
}

And there you have it. The binding expression syntax in your XAML will work seamlessly with this solution. You can specify any type of binding, including the use of valueconverters etc.

Of course, any behaviour you wanted in your data objects cannot be implemented this way, but you shouldn’t mix data and logic anyway :)

 

Dean

Tags: , ,

Comments


February 3. 2010 08:00
trackback
Trackback from DotNetKicks.com

Using CLR 4 Dynamics To Mock Bindable Objects in XAML


February 3. 2010 08:29
trackback
Trackback from DotNetShoutout

ButtonChrome.com | Using CLR 4 Dynamics To Mock Bindable Objects in XAML


February 9. 2010 17:10
Derek Lakin
Hi Dean,
I like the idea, but what does this add over the built-in support for design-time data that is available in both Visual Studio and Expression Blend?

One other question:  how does your solution cope with switching between design-time and run-time data?

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



Most comments

Tom Tom
1 comments
Derek Lakin Derek Lakin
1 comments
gb United Kingdom
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010 ButtonChrome.com