Developing a Robust Data Driven UI Using WPF – An Overdue Summary (and full source code)

.NET, Software Development, WPF April 15th, 2009

I wrote the stocky application more than a year ago as a research project aimed at proving that using WPF we can separate presentation metadata (XAML) from program logic. The goal was to provide the Duet team at SAP with a document reference sample for using M-V-VM to achieve this separation.

I started documenting the proof-of-concept in a series of posts but unfortunately after leaving SAP my interests (and work) shifted away from WPF and I didn’t find the time to finish the series.

I’ve received numerous requests to release the source code but I couldn’t do so because it was part of a larger infrastructure code I wrote at SAP which basically ads a lot of noise to the sample (an d probably ads legal issues for me sharing it).
Anyway, I took some time off this afternoon to re-write the sample independently so that I could share it:

This, I guess is the long overdue ending for the series:

  • Introduction – introduces the concept of M-V-VM and the reasoning behind it.
  • The DataModel – describes how to write the Model part of our application.
  • Stock DataModel Sample – provides a conrete implementation of a Stock model and its view.. 

However, If you’re interested in M-V-VM in WPF, there are numerous topics worth mentioning that I didn’t get to cover and are definitely worth checking out:

Unit Testing

As I said in the introduction post, one of the most important benefits of seperating the logic code from the presentation (XAML) is that its straightforward to unit test. In fact, my next post following the Stock DataModel Sample was going to be about unit testing – specifically, how to test the DataModel its provider which, because of the use of threading, is a bit tricky.

This post is actually 99% done in the comments of the unit test code that’s in DefaultStockQuoteProviderTest.cs in the  provided source code. So do yourself a favor and go over the code. It’s not long and very well documented…

Using Lambda Expression for DataBinding

Data-binding is pretty much at the heart of the M-V-VM concept and it makes us write Value Converters which is pretty tedious and annoying.
Wouldn’t it be great if we could replace writing lots of IValueConverter classes like this:

<TextBlock Foreground="{Binding Change, Converter={StaticResource StockForegroundConverter}}" … />

[ValueConversion(typeof(double), typeof(Brush))]
public class StockChangeToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double change = (double)value;
        if (change == 0) return Brushes.Black;
        return (change < 0) ? Brushes.DarkRed : Brushes.Green;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return double.NaN;
    }
}

To just the following XAML statement that embeds the conversion logic:

<TextBlock Foreground="{Binding Change,

Converter={ change=> if (change == 0) return Brushes.Black; return (change < 0) ? Brushes.DarkRed : Brushes.Green; }}" … />

M. Orçun Topdağı wrote an excellent series on using Lambda Expressions for data-binding in WPF to achieve just that:

Reference Applications and Guidance

I haven’t seen a lot of sample WPF LOB reference applications out there but here are some interesting links for further learning:

Tags: , , , ,

Developing a Robust Data Driven UI Using WPF – Stock DataModel Sample

.NET, Software Development, WPF March 30th, 2008

On the previous post in this series we looked into the DataModel component in our architecture in detail and defined an abstract DataModel base class to derive our models from. On this post we’ll implement a concrete data model to represent a stock’s value. Why stock? It’s an object with a changing value that requires our DataModel constantly refresh and keep its data “alive”, and it’s simple to implement which makes it a perfect example for our first DataModel. The first thing we’ll do when defining our Stock DataModel is abstract the data source. This way we can easily implement several data sources for fetching a stock’s data and instantiate the DataModel with the right one (for example, read from Yahoo at runtime, read from fake data source during unit testing):

/// <summary>
/// Defines the interface allowing <see cref="StockDataModel"/> to read quotes from various providers.
/// </summary>
public interface IStockDataProvider
{
    /// <summary>
    /// Gets a given stock symbol's (given by <paramref name="symbol"/>) data.
    /// </summary>
    /// <param name="symbol">The stock's symbol.</param>
    /// <param name="name">The stock's company name.</param>
    /// <param name="quote">The last stock's quote.</param>
    /// <param name="change">The stock's change value.</param>
    /// <param name="open">The stock's open value.</param>
    /// <returns><b>True</b> if data was retrieved successfully; otherwise, <b>False</b>.</returns>
    bool TryGetData(string symbol, out string name, out double quote, out double change, out double open);
}

Now that we have our data source defined we can implement different stock data providers for our DataModel to consume. Now, lets go over the StockDataModel class:

public class StockDataModel : DataModel
{
    private string _symbol;
    private IStockDataProvider _quoteProvider;
    public StockDataModel(string symbol, IStockDataProvider provider)
    {
        _symbol = symbol;
        _quoteProvider = provider;
        this.State = DataModelState.Fetching; 

        // Queue a work item to fetch the symbol's data
        if (!ThreadPool.QueueUserWorkItem(new WaitCallback(FetchDataCallback)))
        {
            this.State = DataModelState.Invalid;
        }
    } 

    public string Symbol
    {
        get { return _symbol; }
    }

Our StockDataModel constructor takes the stock symbol that the model represents and an IStockDataProvider to fetch the stock’s data from. We set the initial DataModel state to Fetching and queue a work item for a background thread to update our model with the stock’s data – company name, quote, change value and open value. If we fail to queue the work item than we put the model in an invalid state. Next, we need to define the properties exposed by StockDataModel for data binding.

public string Name
{
    get
    {
        VerifyCalledOnUIThread();
        return _name;
    }
    private set
    {
        VerifyCalledOnUIThread(); if (_name != value) { _name = value; OnPropertyChanged("Name"); }
    }
}
public double Quote
{
    get
    {
        VerifyCalledOnUIThread(); return _quote;
    }
    private set
    {
        VerifyCalledOnUIThread(); if (_quote != value) { _quote = value; OnPropertyChanged("Quote"); }
    }
}
...


We’re sign a private setter to update the property values and trigger a PropertyChanged event if required. You can also add calculated properties. For example:

public double ChangePercent
{
    get
    {
        if (double.IsNaN(Change))
            return double.NaN; 

        if (double.IsNaN(Open))
            return double.NaN; 

        try
        {
            double change = (Change / Open) * 100; return change;
        }
        catch
        {
            return double.NaN;
        }
    }
}

In this case, it is important to remember to trigger the property change event for ChangePercent too when the values it depends on change… Now for the implementation of the FetchDataCallback. This method will be called by a background thread to update the stock data. Since this method is called by a background thread we’re free to perform expensive operations, such as calling a web service to fetch the stock’s data from an online provider (like Yahoo).

private void FetchDataCallback(object state)
{
    string fetchedName;
    double fetchedQuote;
    double fetchedChange;
    double fetchedOpen;

    if (_quoteProvider.TryGetData(_symbol, out fetchedName, out fetchedQuote, out fetchedChange, out fetchedOpen))
    {
        this.Dispatcher.BeginInvoke(
            DispatcherPriority.ApplicationIdle,
            new ThreadStart(
                delegate
                {
                    this.Name = fetchedName;
                    this.Quote = fetchedQuote;
                    this.Change = fetchedChange;
                    this.Open = fetchedOpen;
                    this.State = DataModelState.Active;
                }));
    }
    else
    {
        this.Dispatcher.BeginInvoke(
            DispatcherPriority.ApplicationIdle,
            new ThreadStart(
                delegate
                {
                    this.State = DataModelState.Invalid;
                }));
    }
}

On the previous post, on the WPF threading model overview we noted the following:

If only the creator of a DispatcherObject can access it, how can a background thread interact with the user? The background thread does not access the UI directly but it can ask the UI thread to perform a task on its behalf by registering work items to its Dispatcher using it’s Invoke (for a synchronous call that returns when the UI thread finished executing the delegate) or BeginInvoke methods (which runs asynchronously)

In the above code, after fetching the data on the _quoteProvider.TryGetData we need to communicate these changes back to the UI thread. We use the Dispatcher to set the new values for the DataModel properties which ensures that our property change events will be triggered on the UI thread.

Keeping the Data Alive

So far, our code only fetches the stock data once. Lets see what it takes make out DataModel keep its data alive.

protected override void OnEnabled()
{
    _timer = new DispatcherTimer(DispatcherPriority.Background);
    _timer.Interval = TimeSpan.FromMinutes(5);
    _timer.Tick += delegate { ScheduleUpdate(); };
    _timer.Start(); 

    ScheduleUpdate();
}
protected override void OnDisabled()
{
    _timer.Stop();
    _timer = null;
}
private void ScheduleUpdate()
{
    VerifyCalledOnUIThread();
    // Queue a work item to fetch the quote
    if (ThreadPool.QueueUserWorkItem(new WaitCallback(FetchDataCallback)))
    {
        this.State = DataModelState.Fetching;
    }
}

The above code defines a timer that is active when the DataModel is Enabled. The timer calls ScheduleUpdate every 5 minutes to perform the same data update using a background thread logic we performed on our constructor. We’re using a DispatcherTimer so that the calls to ScheduleUpdate will be made using the Dispatcher’s thread (the UI thread) so that we can update the DataModel’s state without a hassle. If we had used System.Threading.Timer then ScheduleUpdate would be called on the timer’s thread requiring the use of Dispatcher.BeginInvoke to update the state…

That’s it…

We’ve got the basic DataModel implemented. You can using it in you’re XAML window to see it working… To get a basic XAML running you’ll need to define a content control:

<ContentControl x:Name="_content" />

And set its content to a StockDataModel instance on your codebehind:

_content.Content = new StockDataModel("AAPL", someProvider);

Then all you need to do is define a data template for the StockDataModel type to control it’s appearance. Here’s a simple template for example:

<DataTemplate x:Name="StockTemplate" DataType="{x:Type local:StockDataModel}">

   <StackPanel Orientation="Horizontal" mdb:EnableModel.DataModel="{Binding}" Height="30px" Width="Auto" ClipToBounds="True">

     <TextBlock Text="{Binding Name}" Foreground="#737271" Width="120" Padding="3,0,0,3" Style="{StaticResource StockText}" /> 

     <TextBlock Text="{Binding Quote}" Foreground="#737271" Width="55" Padding="0,0,0,3" Style="{StaticResource StockText}" />  

   </StackPanel> 

</DataTemplate>

You can find the code discussed in this article plus my own implementation for an IStockDataProvider that reads stock data from Yahoo here: On the next post we’ll discuss DataModel unit testing and see how the StockDataModel tests are implemented.

kick it on DotNetKicks.com

Comments (5) imported from www.ekampf.com/blog/:

Sunday, March 30, 2008 10:45:52 PM (GMT Daylight Time, UTC+01:00)

Thanks for the series! Looking forward for the following parts. However, there’s a bug in the shown code as you cannot check if a value is NaN by comparing to double.NaN. You have to use double.IsNaN(…).

Use IsNaN to determine whether a value is not a number. It is not possible to determine whether a value is not a number by comparing it to another value equal to NaN.

Simon Monday, March 31, 2008 4:39:37 AM

(GMT Daylight Time, UTC+01:00)

Hey Simon, Thanks.

Fixing the code and the post…

Regards,
Eran

Eran Kampf

Friday, April 04, 2008 3:47:12 AM (GMT Daylight Time, UTC+01:00)

Very nice article series. Keep up the good work!

Kevin Kerr

Wednesday, May 28, 2008 2:55:06 PM (GMT Daylight Time, UTC+01:00)

Really great series, very nicely done.

Question: Why call VerifyCalledOnUIThread() in the ScheduleUpdate method? Since you’re calling BeginInvoke on the dispatcher inside FetchDataCallback all should be well, right?

Mike

Thursday, May 29, 2008 11:41:31 AM (GMT Daylight Time, UTC+01:00)

Hi Mike,

Good question. Notice that besides calling queuing a work item that calls FetchDataCallback, the ScheduleUpdate method also updates the model’s State to DataModelState.Fetching when that work item is queued. Since we’re changing the actual model we need to make sure we’re doing it in the UI thread. Alternatively, we could have used a System.Threading.Timer to do the updates ScheduleUpdate() will be called on a background thread directly, but then we couldn’t set the model state to fetching. We’d have to send that back to the UI thread.

Regards,
Eran Kampf

Eran Kampf

Tags: , , , ,

Developing a Robust Data Driven UI Using WPF – The DataModel

.NET, Software Development, WPF March 24th, 2008

imageIn the first post in the series I gave an overview of the pattern we’ll be using.
This post will go deeper into the DataModel, as defined in the previous post:

The DataModel is defined exactly as the Model in MVC; it is the data or business logic that stores the state and does processing of the problem domain.
The DataModel abstracts expensive operations such as data fetching without blocking the UI thread. It can keep data “alive” fetching it periodically from source (example: stock ticket), merge information from several sources etc.
The DataModel is completely UI independent and pretty much straightforward to unit test.

The DataModel exposes data in a way that makes it easily consumable by WPF. As such, all if its public APIs, called by WPF for data-biding, must be called on the UI thread only. It must not block the UI thread because we want a robust functional UI so it usually performs operations on a background thread using the Dispatcher to send results back to the UI thread.

Therefore, the simplest DataModel implementation exposes several public Properties that expose data, implements INotifyPropertyChanged and/or INotifyCollectionChanged, and it abstracts the way information is fetched (using background threads to avoid blocking the UI thread when fetching the data is an expensive operation).

For two-way binding a commit and rollback mechanism, a dirty flag, etc.&nbsp; We’ll get to that later on…

As the DataModel implementation needs to abstract expensive data fetching operations and work with multiple threads we need some basic understanding of WPF’s threading model before we look at the DataModel implementation…

WPF Threading Model – A Quick Overview

A typical WPF uses two threads:

  • Rendering thread – runs in the background and handles rendering
  • UI thread – Receive inputs, handles events, paints the screen and runs application code.

The UI thread queues work items in a Dispatcher object. The Dispatcher object selects work items on a priority basis and runs each one to completion.
Every UI thread must have at least one Dispatcher, and each Dispatcher can only use one thread to execute work items.

Therefore, in order to build responsive UI that doesn’t block the UI thread, the application has to maximize the Dispatcher’s throughput by keeping work items small as to minimize the time the Dispatcher spends on processing them – which keeps other work items waiting causing the UI to lag.

In order to perform expensive operations without blocking the UI thread we can use a separate thread that will run in the background, leaving the UI thread free to process items in the Dispatcher queue. When the background thread is done processing it can report results back to the UI thread for display.
Doing this isn’t trivial as Windows only allows UI elements to be accessed by the thread that created them. This means that the background thread we used for some long-running task cannot access and update our UI when it is finished (or during work to show progress) – a background thread updating a control (such as a list box) during its rendering can cause strange UI behaviors that this limitation is there to prevent.

WPF uses the following design to enforce this kind of coordination between the UI thread and other threads:
Most of the classes in WPF derive from DispatcherObject. During construction, a DispatcherObject stores a reference to the Dispatcher&nbsp;linked with the current running thread – creating an association between itself and the thread that created it.
At the beginning of every method in the DispatcherObject, it calls VerifyAccess which compares the Dispatcher associated with the current thread with the Dispatcher stored during the object’s construction – if they do not match it throws an exception.

If only the creator of a DispatcherObject can access it, how can a background thread interact with the user?
The background thread does not access the UI directly but it can ask the UI thread to perform a task on its behalf by registering work items to its Dispatcher using it’s Invoke (for a synchronous call that returns when the UI thread finished executing the delegate) or BeginInvoke methods (which runs asynchronously)

The DataModel Class

So now, after the brief discussion on the use of the Dispatcher we can start coding our base DataModel class.
We’ll start with the simple class and constructor definition:

public abstract class DataModel : DispatcherObject, INotifyPropertyChanged
{
    public DataModel()
    {
    }


We’re deriving from DispatcherObject because we need to have the Dispatcher available so that we can run background jobs that dispatch results to the UI thread.

As discussed earlier, each call to the DataModel should be made on the UI thread. Therefore we would like to enforce that limitation at the beginning of each publicly exposed API. The DispatcherObject class that we derived from contains a VerifyAccess() method that does just that. The method is public but unfortunately marked with the [EditorBrowsable(EditorBrowsableState.Never)] attributes which will make it hard to find for developers using driving their data model from our class.

To resolve this I simply defined a protected method as follows:

/// &lt;summary&gt;
/// Makes sure the call is in the correct thread (the UI thread) by comparing the current dispatcher
/// object with the dispatcher we got when the DataModel was created.
/// &lt;/summary&gt;
[System.Diagnostics.Conditional("Debug")]
protected void VerifyCalledOnUIThread()
{
    this.VerifyAccess();
}

This method will be visible to anyone deriving from our class and it simply calls VerifyAccess to make sure code is made from the UI thread.
The Conditional attribute makes this code execute only in debug bits avoiding this kind of assertion on retail bits – some performance gain.

In order to support asynchronous data fetching the DataModel should encapsulate the information about its state – valid (data fetched), invalid (error fetching data), fetching (processing).

public enum DataModelState
{
    /// &lt;summary&gt;
    /// The model is fetching data
    /// &lt;/summary&gt;
    Fetching,
    /// &lt;summary&gt;
    /// The model is in an invalid state
    /// &lt;/summary&gt;
    Invalid,
    /// &lt;summary&gt;
    /// The model has fetched its data
    /// &lt;/summary&gt;
    Active
}

The data model’s state is exposed using a property:

public DataModelState State
{
    get
    {
        VerifyCalledOnUIThread();
        return _state;
    }
    set
    {
        VerifyCalledOnUIThread();
        if (value != _state)
        {
            _state = value;
            OnPropertyChanged("State");
        }
    }
}

We also implement INotifyPropertyChanged to allow the model to communicate changes in its values.
Since adding\removing event handlers to the PropertyChanged event is a public API exposed by the DataModel, it also requires verification that calls to it are made from the UI thread. We’ll define our own add\remove handlers in order to perform this verification:

protected virtual void OnPropertyChanged(string propertyName)
{
    VerifyCalledOnUIThread();

    if (_propertyChangedEvent != null)
    {
        _propertyChangedEvent(this, new PropertyChangedEventArgs(propertyName));
    }
}

#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged
{
    add
    {
        VerifyCalledOnUIThread();
        _propertyChangedEvent += value;
    }
    remove
    {
        VerifyCalledOnUIThread();
        _propertyChangedEvent -= value;
    }
}
#endregion

Any property that we’ll add to our data model will call OnPropertyChanged on its setter in order to notify it has changed.

It’s Alive!

One more ability we’d like to add to our DataModel class is the ability to enable\disable it.
As defined earlier, the DataModel encapsulates the logic of fetching data and keeping it “alive” and up to date. To do that, it’ll need to keep some internal timer for updating information or register to some change notification event on its source.
This will keep the DataModel alive and can result in memory leaks, which is why we need some way to turn the DataModel on and off, allowing it to unregister from its data sources when that connection is no longer required:

public bool Enabled
{
    get
    {
        VerifyCalledOnUIThread();
        return _isEnabled;
    }
    set
    {
        VerifyCalledOnUIThread();
        if (value != _isEnabled)
        {
            _isEnabled = value;
            OnPropertyChanged("Enabled");
        }
    }
}

public void Enable()
{
    VerifyCalledOnUIThread();

    if (!_isEnabled)
    {
        this.Enabled = true;
        OnEnabled();
    }
}

public void Disable()
{
    VerifyCalledOnUIThread();

    if (_isEnabled)
    {
        this.Enabled = false;
        OnDisabled();
    }
}
protected virtual void OnEnabled()
{
}
protected virtual void OnDisabled()
{
}

When binding UI elements to the DataModel we’ll need some mechanism to enable the DataModel when the element is loaded and disable it when the element is unloaded. There’s an elegant way to implement this behavior which we’ll implement in a future post.

That’s it! We’ve got a basic class to derive out data models from. Note that we’re only addressing one-way data binding for the moment. We’ll address a two-way data model (which requires the ability to commit\rollback data etc.) in future post.

On the next post we’ll look into a concrete DataModel implementation for our Stocky application.

You can download the code for this post from here:

&nbsp;

Further Reading

kick it on DotNetKicks.com

Tags: , , , ,