.NET & Funky Fresh

Syndication

News

  • <script type="text/javascript" src="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&amp;MarketPlace=US&amp;ID=V20070822/US/bluspiconinc-20/8001/8b68bf4b-6724-40e7-99a5-a6decf6d8648"> </script>
Dispelling a Common WPF/SL Myth

Everywhere I look I find WPF/Silverlight developers who believe a very popular myth:  You cannot update a ViewModel or an ObservableCollection from a non-UI thread.  Like most myths, there is an element of truth here.  But not understanding that truth can lead you to some very elaborate solutions.  Here’s the truth: You cannot fire the change notification from a non-UI thread.  So with that in mind, it becomes very easy to abstract thread synchronization away.  Here’s how we do it in Caliburn:

public abstract class PropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public virtual void NotifyOfPropertyChange(string propertyName)
    {
        Execute.OnUIThread(() => RaisePropertyChangedEventImmediately(propertyName));
    }

    public virtual void RaisePropertyChangedEventImmediately(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class BindableCollection<T> : ObservableCollection<T>, IObservableCollection<T>
{
    public BindableCollection() {}

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        Execute.OnUIThread(() => RaisePropertyChangedEventImmediately(e));
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        Execute.OnUIThread(() => RaiseCollectionChangedEventImmediately(e));
    }

    public void RaiseCollectionChangedEventImmediately(NotifyCollectionChangedEventArgs e)
    {
        base.OnCollectionChanged(e);
    }

    public void RaisePropertyChangedEventImmediately(PropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
    }
}

The Execute.OnUIThread is a helper that Caliburn provides to abstract away the underlying IDispatcher.  When Caliburn’s dispatcher is asked to execute something on the UI thread it first checks the thread it is on.  If it is already on the UI thread, it simply invokes the delegate normally.  Otherwise it marshals the call to the UI thread.  This approach also makes testing easy, because you will never find any threading code in a ViewModel.  Everything ultimately goes through an IDispatcher which Caliburn provides a fake implementation of for testing purposes.


Posted 09-08-2009 12:13 PM by Rob Eisenberg
Filed under: , , , ,

[Advertisement]

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)