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.  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 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:

/// <summary>
/// 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.
/// </summary>
[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
{
    /// <summary>
    /// The model is fetching data
    /// </summary>
    Fetching,
    /// <summary>
    /// The model is in an invalid state
    /// </summary>
    Invalid,
    /// <summary>
    /// The model has fetched its data
    /// </summary>
    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:

 

Further Reading

kick it on DotNetKicks.com

Similar Posts:

Tags: , , , ,


15 Comments to “Developing a Robust Data Driven UI Using WPF – The DataModel”

  1. JAH | September 6th, 2008 at 11:03 pm

    Lines of code are cut off in this post. Is there a place I can examine the code?

    Regards

  2. ekampf | September 6th, 2008 at 11:34 pm

    Hi JAH,
    Thanks for the heads up. Layout must have gone bad with my latest migration to WordPress.

    I’ve fixed the post and the code should be clear and visible now.

    I will post complete code for the Stocky sample application very soon.

    Regards,
    Eran

  3. ekampf | September 6th, 2008 at 11:43 pm

    The file for this post is available at:

  4. JAH | September 7th, 2008 at 1:52 am

    Hi Eran,

    Ther is a reference to what I think is a function call to “VerifyPropertyNameIsValid(propertyName);” but I can’f find the function?

    Regards

  5. JAH | September 7th, 2008 at 2:11 am

    Hi Eran,

    I found it, Thanks

    Regards

  6. ekampf | September 7th, 2008 at 12:17 pm

    Fixed paragraphs etc. too

  7. Joel | September 7th, 2008 at 4:29 pm

    Eran,

    I’m a VB.Net developer and am having some dificulty translating the C#.NET code (Especially the event handling code). Is there going to be a VB.NET version of this code? Is it posible to send you what I have so far to proof? This way we can put a VB.Net version out there?

    Thanx
    Joel

  8. ekampf | September 7th, 2008 at 9:10 pm

    Hi Joel,
    There isn’t going to be a VB version (at least not by me) as I won’t be a very helpful proof reader as I have never used it.

    However, the only event handling code here is the very basic of defining a delegate variable – _propertyChangedEvent, and calling it.

    You can find code sample for implementing INotifyPropertyChanged here:
    http://msdn.microsoft.com/en-us/library/ms229614.aspx

    Let me know how it goes…

    Regards,
    Eran

  9. Joel | September 8th, 2008 at 3:47 am

    Hi Eran,

    Can you explain the following statements, I think I know what it’s doing but not sure. Is it adding and removing event handlers from a generic list?

    public event PropertyChangedEventHandler PropertyChanged
    {
    add
    {
    VerifyCalledOnUIThread();
    _propertyChangedEvent += value;
    }
    remove
    {
    VerifyCalledOnUIThread();
    _propertyChangedEvent -= value;
    }
    }

    Thanx
    Joel

  10. ekampf | September 8th, 2008 at 6:20 pm

    Hi Joel,
    We override the default behavior of the event’s Add\Remove to verify they’re only called from the UI thread.

    As written in the post:

    “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.”

    Regards,
    Eran

  11. Joel | September 8th, 2008 at 10:19 pm

    Hi Eran,

    Not being a C# developer I was trying to interpret what the “_propertyChangedEvent += value;” was doing. Is it placing an event into a generic list of events?

    Thanx
    Joel

  12. Joel | September 9th, 2008 at 7:43 pm

    Hi Eran,

    I figured it out and completed a VB.Net version of your code that works, would you like a copy to post for those that only know VB.Net?

    Regards

  13. ekampf | September 9th, 2008 at 10:19 pm

    Joel,
    Glad to hear you got the thing working. I’ll be glad to check it out and add to it the post (or link external to your site if you have one)

    Regards,
    Eran

  14. Joel | September 9th, 2008 at 11:37 pm

    Hi Eran,

    How can I get the code to you?

    Regards

  15. ekampf | September 10th, 2008 at 12:09 am

    email to eran at ekampf.com

Leave a Comment