In my APIMASH Starter Kit for EventbriteAPI, I included the View Models in a Portable Class Library project (APIMASH Eventbrite Core). As I mentioned in earlier posts, I chose this approach so I could reuse them in both of my apps (Windows 8 and Windows Phone 8).
I also wanted to go a bit further, and with the goal of making the creation of view models for similar projects easier, I included in one of the portable libraries (APIMASH Core library, for more info see this post) reusable base classes that take care of most of the common tasks I went through as I was implementing the code for the creation of view models in my Starter Kit.
These tasks are the implementation of the interfaces INotifyPropertyChanged and INotifyDataErrorInfo, as well as providing a way to implement the mapping process from a Data Transfer Object (DTO).
INotifyPropertyChanged and INotifyDataErrorInfo
If you are a XAML developer you are probably very familiar with these interfaces. Through INotifyPropertyChanged, the XAML infrastructure “knows” when a property changes in the underlying object that is bound to a control, and therefore update the control accordingly. Similarly, when a change occurs in a bound property of a control (e.g. UI data entry), the XAML infrastructure, through this interface, updates the underlying object (a View Model).
The INotifyDataErrorInfo interface provides a way to implement simple error handling and data validation in your View Models. By implementing this interface you can benefit from the controls that have built-in mechanisms to use this interface to determine whether an error has occurred. You can also use it in your application logic to determine the state of a ViewModel and make decisions in your code accordingly. For example you can programmatically validate if the user has entered all the information the application needs before making an API call.
The following figure shows the implementation of both of these interfaces in the base class ApiMashBindable included in the APIMASH Core portable library.
From the code above, you can see that the implementation of the INotifyPropertyChanged is fairly standard but with the addition that I check for errors when a new value is set, and if the new value changes the error state of the view model, I raise the event OnErrorStateChanged from INotifyDataErrorInfo
The error state changes when either the new value of the given property is invalid (i.e. a transition to an error state) or or when the value is now valid and the previous one was not (i.e. a transition from an error state to a valid state).
You probably have also noticed that the actual validation of the property occurs in ValidateProperty().
The default implementation of this method will return string.Empty for all properties -i.e. no error. If I want to implement a validation for a particular property in my view model, I just override ValidateProperty() and based on the property name and the new value, I could perform the necessary validation.
This also brings the important point that in order for this to work, in concrete implementations of this class, when I call the method SetProperty<T> I need to pass the property name. The following figure shows a sample implementation of a EventbriteAPI Starter Kit View Model.
Loading Data and Mapping
One important feature I wanted to provide, is the availability to control when in the overall lifecycle of the application, the application loads the data. For this, I created a base View Model with one abstract method, LoadDataAsync(). This method could be overridden by a derived class and the applications can control when to load the data in the instances of this class, by calling this method at the appropriate time.
The following figure shows the base class ApiMashBaseViewModel.
The following demonstrates a class that extends this base class by overriding the LoadDataAsync() method with an API call and mapping logic. The API call returns a ExpandoObject as the DTO and I map the results to the view model
Note that I noticed that some of the properties from the EventbriteAPI response were not available in all the results,
that’s why I check if the property exist before attempting to get it.
In the blog post, I discussed how I included in a portable library a base view model that implements the interfaces INotifyPropertyChanged and INotifyDataErrorInfo as well as the approach I followed to control how the data is loaded and mapped to the view model.