Introduction
In my previous article we learned how to display sample data in design mode (Visual Studio / Blend) by implementing a simple Puzzle app.
The questions that probably comes to our head once read this article is… Ok this is fine for simple scenarios, what about real life ones? How does it integrate with Web Services / Asynchronous Requests ? How does this fit in a well architected MVVM application?
In this videoarticle we will cover these topics by implementing an application that will read from an Apple movies feed (service request) and display the results in a GridView.
Let’s take a quick look at what we want to implement!
Sample 1 – Simple way to display sample data
Let’s start by creating the plumbing needed to read from the remote feed and parse the results. If we just setup the service call and try to instantiate the ViewModel as a design data context we will get a crash. Why? When you declare your design DataContext as IsDesignTimeCreatable, the ViewModel gets instantiated when you display the XAML page, if Blend or Visual Studio find a call to a Web Service or DB call they will fail.
What can we do then? A simple approach is to detect in the ViewModel constructor if we are in design mode and in that case display sample data. Let’s check how to do that!
The main advantage of this approach is that we can tailor the sample data that we want to show for each ViewModel.
The disadvantages are: it can become a pain in the neck to create and maintain the sample data for each ViewModel, the ViewModel gets dirty with that sample data and it doesn’t follow the natural application execution flow.
Sample 2 – Interfaces and Mocks
Wouldn’t it be nice to isolate all this test data in a separate class and avoid having to code the data in the ViewModel itself?
We have already encapsulated the repository methods (GetMovies) in a class:
- What if… we define the operations that we want to expose in a interface (contract).
- What if… we implement a version that inherits from the given interface that returns dummy data? (a mock, no real service call involved, simulated).
- What if… we just check if we are in design mode to instantiate the real repository implementation or the mock class.
Let’s take a look at how to implement this!
The main advantage of this approach is that the sample data gets encapsulated in a separate class, but still we need to implement some plumbing in the ViewModel (check if we are in design mode).
In the next sample we will go for a cleaner approach that will allow us to have a “design mode” agnostic ViewModel.
Sample 3- MVVM Light full integration
We are almost there ! Wouldn’t it be great to isolate all the “real / fake” repository instantiation in a locator class? This will let us get rid of the “design data context” and directly refer in the XAML to the real data context.
We are going to take benefit of MVVM Light Toolkit(*) to make this job, the steps we are going to follow:
- Use the Locator + SimpleIOC to register real or mock repository class to initialize the ViewModel.
- Add a parameter in the ViewModel constructor to request a IRepository to be instantiated (the IOC engine will take care of that instantiation automatically).
- Remove the need of a design data context, we can just now declare the real data context in the page XAML markup (the locator will take care of instantiating the ViewModel and check if we are in design mode or not).
(*)If you are new to MVVM and MVVM Light Toolkit I fully recommend you go through the excellent Gill Cleeren’s Windows 8 MVVM Webinar before proceeding to this last video.
By using this approach we have completely isolated the real / sample repository instantiation from the ViewModel, it all gets encapsulated in the Locator and it can serve us as well to easily add unit testing to our ViewModel logic (we can mock the repository and focus on testing the ViewModel Business Logic).
Summary
In this article we have learnt how we can add Blendability to real life scenarios and how we can solve the design time data issue starting from a simple approach to a more elaborated one.