Using the DataStateBehavior for “Loading animations” in MVVM

Behaviours are growing in importance within Blend – especially for developing Silverlight and WPF apps using the MVVM pattern.  In fact they are becoming so useful we have to wonder when they will be made available in the editor of VS 2010.

A couple you should definitely look at, if you haven’t already done so when using MVVM, are the CallMethodAction and InvokeCommandAction that make it easy to wire up a Method or Command in your ViewModel using the Blend editor.

However a new one that now ships in box with Blend 4 offers something a little more interesting and perhaps less obvious.  This is the DataStateBehavior which allows you to change to a Control State depending on a property of your ViewModel.  This struck me as an easy way to provide an animation when your ViewModel is doing some async work.

Lets take a simple example.  First the ViewModel.  This has a single method called DoWork that simulates a few seconds of work (e.g. calling an async service) and a property called IsWorking that can be set to true whenever the ViewModel is doing some prolonged work.  One way to handle this in a more complex scenarios when you could possible have multiple async calls happening is to have a counter that you increment whenever you start some work and the decrement when you stop work.  Whenever the counter is positive then you should display your “loading animation” which we’ll achieve through the DataStateBehavior.  Here it is:

   1: public class MainPageViewModel : INotifyPropertyChanged

   2: {

   3:  

   4:     private bool _isWorking;

   5:     public bool IsWorking

   6:     {

   7:         get

   8:         {

   9:             return _isWorking;

  10:         }

  11:         set

  12:         {

  13:             _isWorking = value;

  14:             RaisePropertyChanged("IsWorking");

  15:         }

  16:     }

  17:  

  18:     private int _workCount;

  19:     private int WorkCount

  20:     {

  21:         get

  22:         {

  23:             return _workCount;

  24:         }

  25:         set

  26:         {

  27:             if (value < 0) value = 0;

  28:             _workCount = value;

  29:             IsWorking = _workCount > 0;

  30:         }

  31:     }

  32:  

  33:     public void DoWork()

  34:     {

  35:         //simulate some work

  36:         WorkCount++;

  37:         DispatcherTimer timer = new DispatcherTimer();

  38:         timer.Interval = TimeSpan.FromSeconds(3);

  39:         timer.Start();

  40:         timer.Tick += (sender, args) =>

  41:         {

  42:             WorkCount--;

  43:             timer.Stop();

  44:         };

  45:         

  46:     }

  47:  

  48:     public void RaisePropertyChanged(string propertyName)

  49:     {

  50:         if (PropertyChanged != null)

  51:         {

  52:             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

  53:         }

  54:     }

  55:  

  56:     public event PropertyChangedEventHandler PropertyChanged;

  57: }

 

In Blend I first set the DataContext for the User Control to this ViewModel

image

Which looks like this in Xaml and will instantiate the ViewModel and set it as the DataContext for this View (UserControl)

image

I drew a big button on the artboard and then created a couple of states called “Working” and “NotWorking”.  I had a bit of fun setting some effects and animations for the state transitions.  In particular I made sure the animation for the Working state was set to auto-reverse and repeat forever.

image

Now comes the fun bit by using Blend behaviours to wire up the click event on the button to the DoWork method in the ViewModel and then to use the DataStateBehavior to change between the Working and NoWorking states based on the IsWorking property on the ViewModel.

First to wire up the Do Work Method (Note there is also an InvokeCommandAction you can use if you have a command on your ViewModel rather than a simple method I have created here).  To do this you simple drag the CallMethodAction from the Behaviors section in the assets panel and set the properties as shown below:

image

To wire up the DataStateBehavior the process is similar – drag it from the behaviour from the assets panel and set the properties as shown:

image

This looks like this in XAML:

image

And that’s it!  Running the app and clicking the button will run your method in your ViewModel and dispay your Working state.  Once the work is complete in the ViewModel the control returns to the NotWorking state. 

This is nice because:

  • The ViewModel knows nothing of the View and so is more easily testable.
  • Everything can be wired up in Blend – no code to write for a designer.
  • The Xaml is actually nice and straight forward to, and easy to understand.

I would like to see Behaviours in the VS2010 too, because I think there is definitely a case for developers taking advantage of this sort of thing, though it wouldn’t take much for them to type in the Xaml directly.

Example project is available from here: http://cid-fb8b852ef1ab0b35.skydrive.live.com/self.aspx/SampleCode/SimpleMVVMLoadingAnimation.zip 

Cheers

Ian

P.S. Don’t forget our Silverlight Masterclass is now touring the UK:  Http://silverlightmasterclass.net – book early!

Advertisement
This entry was posted in Blend 4, Designers, Developers, M-V-VM, Silverlight and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s