The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








I heart FeedBurner

Latest Diggs - Programming

Computers Blogs - Blog Top Sites

Site Hits

Total: 4,881,741
since: 19 Jan 2005

Monostate vs. Singleton : Adventures in WPF Databinding

posted Mon 12 Feb 07

In this previous article, I mentioned how amazingly cool the monostate pattern was. Unfortunately, that coolness is limited, and the monostate pattern actually breaks and falls to pieces in several key scenarios.

When I wrote the code for that article, what was happening was that all the root properties on that model object (ModelRoot class) were of type ObservableCollection<T>. What I didn't realize is that ObservableCollection<T> has intimate knowledge of how WPF bubbles property changed events to the surface of the UI. In other words, when you fill an ObservableCollection<T> with instances of a class that implements INotifyPropertyChanged, the ObservableCollection<T> instance will actually subscribe to those changes, and then manually bubble those changes out to the WPF event dispatcher for you. While this is handy behavior, it can lull you into a false sense of security when implementing the monostate pattern.

Case in point: Implement the monostate pattern to have a single class with a single property called Name. Next, bind your XAML to an instance of that property. Then, create a button that has a handler. In that click handler, create an instance of your model root class and set the Name property to something fancy like "modified". What you'll notice is that your freaking GUI has not changed!! Even though there is but a single subscriber to your PropertyChanged event handler (the WPF event dispatcher), and there is a single source for your data (static member variables), and when you go through the debugger you will see the event fire and you will see the data change, the GUI is never updated!!

Even when you use the dispatcher to forward your event firing to the dispatcher thread, it still won't work. In other words, unless your model root is composed entirely of observable collections, this pattern simply isn't going to work. So, I decided to revisit the singleton pattern (the one I had abandoned in favor of the monostate pattern) and am pleased to report that it actually works.

First, take a look at my model class:

public class ModelRoot : INotifyPropertyChanged
{
    ...
    // member variables .. private, instance-scope...
    private static ModelRoot _instance;

    private ModelRoot() { // initialize member variables }

    public static ModelRoot GetInstance()
    {
        if (_instance != null) return _instance;
        else
        {
           _instance = new ModelRoot();
           return _instance;
        }
    }

    public string Name
    {
        get { return _name; }
        set {
           if (_name != value) {
               _name = value;
              NotifyChanged("Name");
          }
    }

    private void NotifyChanged(string propName)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

}

That's the model class (or at least, the bare bones beginnings of a model class with only a single piece of data (the "Name" property). To create an object provider in your App.xaml file that hosts the new singleton object model, use some XAML that looks like this:

<Application x:Class="modeltest.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml"
             xmlns:model="clr-namespace:modeltest"
    >
    <Application.Resources>
      <ObjectDataProvider MethodName="GetInstance" ObjectType="{x:Type model:MyModel}" x:Key="ModelRoot"/>
     
    </Application.Resources>
</Application>

And of course, to bind a control to this object you use the same syntax you would with a regular object (or a monostate object):

 <TextBlock Text="{Binding Path=Name, Source={StaticResource ModelRoot}}"/>

And finally, to make changes to the model from background threads (for example, if you have data streaming in from a background process that you want reflected in your GUI, and your fabolous monostate pattern model didn't work) you can simply obtain a reference to the singleton instance (the one to which the WPF dispatcher is subscribed!!!) as follows:

MyModel m = MyModel.GetInstance();
m.Name = "Modified";

In short, unless you know you're going to be using observable collections, I'd suggest using the singleton model instance pattern described in this post. It is more reliable, it gets around the instance problem and "event cylo" problems, and its actually pretty easy to refactor your monostate model root class into a singleton model root class. So, I am recanting - don't use monostate as your standard data binding modus operandi, because you will find that it works for a while and then all of a sudden breaks when you do something that is vulnerable to event cylo separation.

p.s. I will be comparing WPF binding to Cocoa binding in an upcoming post. My frustration encountered while debugging the monostate pattern stuff and settling on the singleton pattern plays a pretty big part in my overall opinion of WPF and Cocoa bindings.

tags:            

links: digg this    del.icio.us    technorati    reddit

AddThis Social Bookmark Button




1. ken left...
Tue 13 Feb 07 7:42 pm

I look forward to the comparison. I've been using Cocoa bindings for while, and was looking forward to see how MS implements it with WPF.


Tag Related Posts

WPF Control Development Unleashed

Wed 25 Mar 09 2:26 P GMT-05

SSDS loses an "S" and gains some awesome

Wed 11 Mar 09 11:42 A GMT-05
tags:              

CLINQ v1 Demo - Network Message Filtering

Wed 09 Jan 08 7:47 P GMT-05
tags:        

Building a Ledger Style for WPF Grids

Tue 21 Aug 07 3:30 P GMT-05
tags:    

My first "Acropolis" Application

Mon 04 Jun 07 1:40 P GMT-05
tags:      

Exploring the Delegate Design Pattern

Mon 14 May 07 6:30 P GMT-05

Will Silverlight be DOA?

Mon 16 Apr 07 8:02 P GMT-05

Exploring the MVC Pattern in WPF

Tue 10 Apr 07 12:51 P GMT-05
tags:                      

WPF Bindings == WTF Bindings?

Mon 12 Mar 07 6:31 P GMT-05

On MUDs

Thu 08 Mar 07 5:00 A GMT-05
tags:                    

Cocoa Programming vs. WPF : NIB vs XAML

Tue 20 Feb 07 2:09 P GMT-05

Cocoa Bindings vs. WPF Binding

Thu 15 Feb 07 5:41 P GMT-05
tags:                

Ulysses Agenda Makes Redmond Developer News

Wed 29 Nov 06 7:10 P GMT-05
tags:                

Ulysses Agenda - Network Engine Test 1

Mon 09 Oct 06 2:26 A GMT-05
tags:              

Ulysses Agenda : First Cut Networking Design

Thu 14 Sep 06 12:46 A GMT-05
tags:                  

First Impressions of Windows Vista RC1

Thu 07 Sep 06 1:30 P GMT-05
tags:                      

Localizing a WPF Application

Tue 22 Aug 06 11:39 A GMT-05
tags:            

WPF Slide Show and Photo Album

Fri 18 Aug 06 6:48 P GMT-05

ADO.NET Entity Framework Announced Today!

Wed 16 Aug 06 11:08 A GMT-05

.NET Framework 3.0 June CTP is out!

Fri 23 Jun 06 6:23 P GMT-05
tags:                

Tech-Ed 2006 - Session Reviews

Tue 13 Jun 06 6:22 P GMT-05
tags:                    

Tech-Ed 2006 Day 1 - Registration Day

Sun 11 Jun 06 7:17 P GMT-05

WPF/XAML and LINQ - A match made in heaven

Tue 06 Jun 06 11:32 A GMT-05
tags: