I'm a Jack of all traders but first and foremost a Community Developer and Teacher. I love to rip apart and discover new things and technologies, then break them down and show others how to as well. Father of 4 and maybe just a bit mad as well, I have Monty Python to thank for that. Simon is a DZone MVB and is not an employee of DZone and has posted 73 posts at DZone. You can read more from them at their website. View Full User Profile

MVVMLight and Async

06.15.2012
| 2944 views |
  • submit to reddit

With Windows 8 just around the corner and many developers running for the ship to get up to speed with the new brave world (even those who have frowned at the new Metro interface and possibly wont touch it themselves, still see the value in writing apps / games for the platform to sell).

One of the biggest hurdles I’ve found and seems reflected in colleagues and peers is the new Async framework, granted to those who have followed the Task framework it’s no big shock and a simple evolution, but for those of us who left it in their “Read it Later” pile it is a bitter pill to swallow.  That being said however once you have “tested the waters” so to speak will find it’s not that different from what we already know it’s just another way of tackling the problem of offloading work and marshalling it back for use, but cleaner and easier to read and some notable performance gains by letting the compiler and CLR handle it for us.

This post is simply going to walk though one of the first challenges I set myself when learning Async which was how it affected my core apps with loading data, this is by no means the only reason for ASync’s being, but data is at the heart of most apps and when there is a lot of it to handle you need to effectively load it without dampening the users experience in the front end.

*Note In case you were wondering this post is not just for Windows 8 devs.  The Async CTP is also available for Visual Studio 2010 with variants for .NET/ Silverlight and even Windows Phone. I’ve found by going back to what is already familiar and updating it to Async has helped my journey a lot and my progressions to Windows 8 have been all that smoother for it when porting. The samples attached are in fact written for Windows Phone using Laurent Bugnion’s (GalaSoft) MVVMLight framework for windows phone Resources and Links

First a quick nod to a lot of the links and pages that have helped me in my journey so far.  While there is not a great deal of it yet, more is sure to come.  What there is however is both easy to digest and (where it’s needed) very technical in nature.

    Async MSDN Site - http://msdn.microsoft.com/en-us/async (Especially good are the getting started videos!)

    Building Windows 8 Blog Async Post (courtesy of Mike Taulty) - http://bit.ly/LQwEik (Deep technical article on Task)

    MSDN library page for Async - http://bit.ly/LQwIyJ – Interesting explanations and code walkthroughs

    The Task: Events, Asynchronous Calls, Async and Await (Jeremy Likeness) - http://bit.ly/LQxqvV – A nice clean article for deconstructing Tasks and good practise

Getting Started

Couple of things you’ll need if you want to re-create / use the samples here (you don’t have to of course, you can use everything here just in Windows 8 if you wish!)

    Visual Studio – any version from 2010 upwards including the Windows Phone and express editions

    MVVMLight V4+ – you can either download this from NuGet or from the codeplex site here. (I’d recommend getting it from Codeplex for your first project and then NuGet after that so you also get all the Project/Item templates and snippets it provides.

    Async CTP (only for VS 2010 editions)

* Note

At the time of writing the Async is only a CTP for 2010 and to get it installed on an existing system does present some challenges (which are well worth the pain of going through to get the goodness in 2010).  Primarily it has to do with Updates to Visual Studio since the CTP was released.  it’s not a big deal as all you have to do is uninstall the updates while you install the CTP and then run windows update again afterwards.  In my experience I also had to un-install / re-install the WP developer SDK as well but that may have just been me.

See the following article for helping you get the Async CTP running on VS 2010 (all editions) - http://mikaelkoskinen.net/post/async-ctp-fix-installation-problem.aspx

Here’s hoping a full release will also come out for VS 2010 with the release of VS 2012.

Quick intro to V4 of MVVMLight

With the introduction of V4 of the MVVMLight, Laurent implemented a lot of the new features to the framework from his talk back in 2011 http://bit.ly/LQA70t) – If your completely new to MVVM then I'd also recommend watching his 2010 session which is what got me started in MVVM in the first place (http://bit.ly/LQA4S5)

The core thing that was introduced was “Inversion of Control” (IOC for short) which allows you to decouple the dependencies used in your view models from the actual implementations of those dependencies, the common example used to describe this is where you have view models that require data from a service, through IOC you can supply “Test” data or “Live” data without having to do any complicated code in your view model to handle this, a simple switch loads the appropriate implementation of your data loading function and the View model is unaware that anything is different.

image

The above diagram attempts to show at a high level just what is going on, When the app is started the ViewModelLocator is instantiated, when that happens it registers all the dependant Interfaces and then any concrete classes (in this case our View Models) with the Service locator, then when a page requests a certain view model the view model locator requests the concrete type from the Service Locator which in turn looks at that concrete type and determines if it has any constructor parameters, if it finds any it looks in the Service Repository for another concrete type registered with the interface that is required and instantiates the required class using that type, the instantiated class is then handed back to the view model locator which in turn hands it back to the page for use.  You aren’t limited to only using the IOC service to just the ViewModelLocator so you can in turn apply it wherever you want in your application.

That’s my very high level description of one solution that IOC gives, I'm sure there are many more.  I’m not going to go in depth as to what IOC is or does (that’s what google is for Open-mouthed smile) but just to note it is a nice change in the templates for MVVM and one worth taking advantage of.

There have been many other improvements including Windows 8 support so it’s worth spending a little time walking through the default template that MVVMlight gives you in V4.

Starter for 10

First off before we move to Async a quick look at what you get out of the box now, a starting point if you wish.

With MVVM (as the definition of the name suggests) we have a Model, a View Model and a View.  The special bit of magic being the ViewModel part that separates all the Data and Content from the layouts, positioning and animation in the UI (View).  It’s the glue that pulls it all together.

The key thing is that the data (model) has to be loaded from somewhere, usually a Web Service located out on the web or even locally stored on a device (whether it’s from a file or a DB) or even sometimes both so the ViewModel needs to bind all this up together in one coherent list or property that a View can digest without having to worry about how it got there.

In the Template we have a nice basic model:

[CODE HERE]

Just a simple string property to give us the title of the Page, but this could also be a more complex definition detailing the properties of a player (name, description, avatar URL, etc).

One point I would make which is a subject of hot debate regards Lists. My own recommendation is that you should avoid (if at all possible) the use of Lists in a Model, the reason for this is that the model is supposed to define how a single piece of data is represented, if that model does include a list of other information (a players achievements for example) then you would have a “PlayerAchievement” model and you would then load the additional list in the “PlayerViewModel” simply because that’s where the data is stitched together for representation in the UI.  Another way to look at it is to treat Models as Individual tables in a database, you cannot put a “List” of items in a single table, you would create a linking table (or parent column) to join them (yes you can still have an array within a single table but you wouldn’t split that data in your model you would decompose it in your view model) [/rant off]

So model aside we next have our basic ViewModel:

view source print?
01 namespace MvvmLightAsync.ViewModel
02 {
03     /// <summary>
04     /// This class contains properties that the main View can data bind to.
05     /// <para>
06     /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
07     /// </para>
08     /// <para>
09     /// See http://www.galasoft.ch/mvvm/getstarted
10     /// </para>
11     /// </summary>
12     public class MainViewModel : ViewModelBase
13     {
14         private readonly IDataService _dataService;
15   
16         /// <summary>
17         /// The <see cref="WelcomeTitle" /> property's name.
18         /// </summary>
19         public const string WelcomeTitlePropertyName = "WelcomeTitle";
20   
21         private string _welcomeTitle = string.Empty;
22   
23         /// <summary>
24         /// Gets the WelcomeTitle property.
25         /// Changes to that property's value raise the PropertyChanged event. 
26         /// </summary>
27         public string WelcomeTitle
28         {
29             get
30             {
31                 return _welcomeTitle;
32             }
33   
34             set
35             {
36                 if (_welcomeTitle == value)
37                 {
38                     return;
39                 }
40   
41                 _welcomeTitle = value;
42                 RaisePropertyChanged(WelcomeTitlePropertyName);
43             }
44         }
45   
46         /// <summary>
47         /// Initializes a new instance of the MainViewModel class.
48         /// </summary>
49         public MainViewModel(IDataService dataService)
50         {
51             _dataService = dataService;
52             _dataService.GetData(
53                 (item, error) =>
54                 {
55                     if (error != null)
56                     {
57                         // Report error here
58                         return;
59                     }
60   
61                     WelcomeTitle = item.Title;
62                 });
63         }
64     }
65 }

Again not much in here but we can see that the “Title” property in out model when read and used by the View model is stored and exposed as the “WelcomeTitle” property which makes more sense for the UI (highlights a nice separation from what we can data to HOW we can consume and use that data, for instance the same model property could be re-used for several View Properties in the View Model)

The new thing (if your experienced with using MVVM) above if that the ViewModel now takes an argument which is an Interface that provides the DataService (or data loader) that will go and get the model data that is required for the ViewModel function to work.  Traditionally this would have been done by a “LoadData” method called by the constructor of the ViewModel which would then either create the data needed or call some helper functions to perform the necessary calls (and these could take some time and hence delay the creation of the ViewModel, possibly affecting the front end performance of the page using it as it’s DataContext)

This example above has a very basic setup as shown below, just one function to Get the string required for the “WelcomeTitle” property, this could just as easy be a request for an enumerable list of model items:


view source print?
1 namespace MvvmLightAsync.Model
2 {
3   public interface IDataService
4   {
5     void GetData(Action<DataItem, Exception> callback);
6   }
7 }
The basic interface explaining what functions are required by default classes implement this interface

view source print?
01 namespace MvvmLightAsync.Model
02 {
03   public class DataService : IDataService
04   {
05     public void GetData(Action<DataItem, Exception> callback)
06     {
07       // Use this to connect to the actual data service
08   
09       var item = new DataItem("Welcome to MVVM Light");
10       callback(item, null);
11     }
12   }
13 }
The DataService class implementing the “GetData” function required by the interface which simply returns a single string in it’s call back.

Usually such functions would return an IEnumerable list of data from file or a web service.

In the sample you will notice there is another implementation of the IDataservice for design time data, in the demo it’s the same but IRL if a web service was used for live data you could supply dummy test local data so you didn’t need the web to test the UI

So we have our Data (model), a View model that presents this data (ViewModel) and a service that will go and get that data for us from somewhere in the correct model format (DataService), all that’s left is to make the ViewModel available to Pages, this is done in the ViewModelLocator which is a handy central local where Silverlight can be instructed to expose all the view models available:

view source print?
01 namespace MvvmLightAsync.ViewModel
02 {
03     /// <summary>
04     /// This class contains static references to all the view models in the
05     /// application and provides an entry point for the bindings.
06     /// <para>
07     /// Use the <strong>mvvmlocatorproperty</strong> snippet to add ViewModels
08     /// to this locator.
09     /// </para>
10     /// <para>
11     /// See http://www.galasoft.ch/mvvm/getstarted
12     /// </para>
13     /// </summary>
14     public class ViewModelLocator
15     {
16         static ViewModelLocator()
17         {
18             ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
19   
20             if (ViewModelBase.IsInDesignModeStatic)
21             {
22                 SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
23             }
24             else
25             {
26                 SimpleIoc.Default.Register<IDataService, DataService>();
27             }
28   
29             SimpleIoc.Default.Register<MainViewModel>();
30         }
31   
32         /// <summary>
33         /// Gets the Main property.
34         /// </summary>
35         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
36             "CA1822:MarkMembersAsStatic",
37             Justification = "This non-static member is needed for data binding purposes.")]
38         public MainViewModel Main
39         {
40             get
41             {
42                 return ServiceLocator.Current.GetInstance<MainViewModel>();
43             }
44         }
45   
46         /// <summary>
47         /// Cleans up all the resources.
48         /// </summary>
49         public static void Cleanup()
50         {
51         }
52     }
53 }

Here’s where we see the Crux of the difference between V3 and V4 where we have replaced static properties for the ViewModel’s with a SimpleIOC container.

As the Data Service is based on an Interface instead of a concrete class we can interchange it with any class that implements that interface, so depending on whether we are running in blend or on a device we can choose which Data Service (the live or design time one) to register and make available for use.

You will notice that when we instantiate the MainViewModel that we are not providing any parameters, but our MainViewModel requires a parameter to be constructed and it does not have any Blank constructors, so where is it getting it from.

This is where the other half of the IOC comes into play, the unseen plumbing that works behinds the scenes to inject what ever dependencies an object needs if it is not provided already (so long as there is one to offer!), as we have registered a data service with the appropriate Interface implementation (either the Design or Live one) with the IOC Service Locator, then at compile/run time the IOC framework will pull it from it’s library and provide it for you.  Very powerful in the right hands.

But AWAIT there's more

So this is all well and good but if you have a lot of data or it’s coming from a backend service which could take a while to gather or worse it has to time out first before you can handle it (some time outs are longer that others), then it could possibly be a lot of time for your user to wait while the page loads.  You might offset this in your page by only loading the data after the page itself has loaded and shown the base UI, but still it could cause the UI to be unresponsive.

Originally to work around this you might use background threads or dispatchers to handle this with call backs and such, using the Dispatcher again to marshal information back to the UI and such (in high performance  scenarios the dispatch can loose a job or two!). *Note, traditional threading and background workers are NOT available in Windows 8, the System.Windows.Threading class is GONE!

So enter ASync and Await, if you’ve watch at least the video from the ASync site you should have a good basic understanding of what the framework gives you (not going to re-iterate it here, watch the videos.  See you in 30 mins if you haven’t!) so how to apply this to the MVVMLight framework, simples.

The main problem we are trying to solve here with ASync is that we want to offload the loading of our data to background threads or workers and have it marshal back so it can be used by the UI (updating your ViewModel updates the UI directly so it has to be on the UI thread, else it will complain !A LOT! ).

Now one of the things that hits you when you start trying to do ASync in the beginning is that it is infectious, once you update a lower part of your application (loading data from the web for example) to use ASync it permeates up the call stack right back up to the first function that called it, adding the “async” modifier to each function and “await” to each method call, which is not idea when you just want to get your data.  Thankfully the last video in the MSDN async video helps us out here and we can apply the same logic to our data calls, treating them as external calls from within the project (some purists might state you should go all the way and have a separate project for handling this, but its not necessary unless you want to roll that way).

So enough talk and lets get on with it!

First off we need a reference to the ASync framework, as shown in the videos its in a bit of an odd place but here is is again in case you’ve forgotten Smile with tongue out

"C:\<My Documents>\Microsoft Visual Studio Async CTP\Samples”

If you cannot see the folder, the ASync library lied to you about it being installed successfully, so be sure to follow the article mentioned earlier about un-installing updates and getting it installed correctly, the folder is added at the end of the install and won’t appear if the necessary changes were not made! (cost me an afternoon finding that out!, you told me you installed successfully damn you)

Just make sure you select the correct DLL for the platform you are building against, thankfully they provide versions for .NET / Silverlight and Phone.  You only need the one for your project type, so don’t add more!!

Next we need to alter the Interface our data services are using so that our calls are returning the right kind of data, were no longer using a call back because the ASync framework manages that all more effectively and just returns data when it’s done automatically (sounds almost too good to be true doesn’t it, no more manual handling of call backs), so we change the interface mentions above to the following:

view source print?
1 namespace MvvmLightAsync.Model
2 {
3     public interface IDataService
4     {
5         Task<DataItem> GetData(CancellationToken cancellationToken);
6     }
7 }

So now instead of a call back, the “GetData” function will return a Task containing data in the form of a “DataItem”.  For lists you can simply replace “DataItem” with “IEnumerable<DataItem>” for example.

The cancellation token is optional of course you don’t have to use then but I would advice you do especially with what could be a long running operation, if the user closes the app it’s nice to close these things down cleanly and stop your backend server sending data to something that isn’t listening any more!

Next we need to update out implementation(s) of this interface, thus:

view source print?
01 namespace MvvmLightAsync.Model
02 {
03     public class DataService : IDataService
04     {
05         #region Public Interface Methods
06   
07         public Task<DataItem> GetData(CancellationToken cancellationToken)
08         {
09             return GetDataInternalAsync(cancellationToken);
10         }
11   
12         #endregion
13   
14         #region Private Interal Async workers
15   
16         private async Task<DataItem> GetDataInternalAsync(CancellationToken cancellationToken)
17         {
18             return await TaskEx.Run(() => new DataItem("Welcome to MVVM Light"));
19         }
20   
21         #endregion
22     }
23 }

Now as I stated I've used the pattern described in the last ASync video to have a seperate public non-async method which calls an internal private async function, this saves on having to change the rest of my project to be async as well and limits the impact.  Nothing stopping you from doing so, it just makes sense to me to only add it where it’s needed.

As you can see in this instance it’s clean and no fuss, in my design Data Service I can forgo the async internal call and just return static hardcoded data and the app is none the wiser (recommended for designing in Blend with example data)

And that’s it, the Task framework handles all the messy background threading, callbacks and marshalling it back to the UI without even a thought.

So do you think that’s easier?

Conclusion

Well that’s a basic intro to Async from me and an example of how MVVM can benefit from it, so I hope you find it useful

I’ll not provide a sample this time as you only have to install the MVVMLight toolkit, create a new MVVMLight project using the template and make the above changes.

I may later through up an RSS reader I helped out one of the guys put together for a more complete web sample, shout below if that’s something you would like.

Published at DZone with permission of Simon Jackson, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)