Getting Started with Xamarin & MVVM Light

This post is part of a three part series of posts of my notes on getting started with Xamarin and Mvvm Light. This posts covers an overview, Resources, lessons learned on the shared View Model code.

The other posts detail step by step instructions for creating the iOS and Android implementations. The full example code is on GitHub.

Overview

Having used the Model-View-ViewModel (MVVM) pattern extensively for a number of years while developing WPF apps I’m interested in using this with Xamarin iOS and Android apps. In the past I’ve used the Model-View-Controller (MVC) pattern and much prefer the MVVM style, there seems to be two well established MVVM frameworks for Xamarin:- Mvvm Cross and Mvvm Light.

The Mvvm Cross framework offers more features than Mvvm Light and I am planning to look into this at some point, however I’ve previously used Mvvm Light with WPF apps so there should be less of a learning curve in trialing this.

As I reacquaint myself with MVVM Light and learn how it works in the context of Xamarin apps I’m blogging some notes and links.

My initial goal is to create a solution with an iOS storyboard app and an Android app sharing the same View Models and in future Models and shared services. I’m interested in learning how to bind the View controls to the View Model and how to navigate between pages so this will be the focus of this post.

Resources

For those with a Pluralsight subscription Laurent Bugnion has an MVVM Light Fundamentals Course.

Laurent’s MVVM Light presentation from Xamarin Evolve 2014.

Laurent also has a guest lecture for those with a Xamarin University subscription - Mvvm Light Toolkit with Xamarin. I found this very useful since he walks us through the sample code generated from the Visual Studio New Project templates when the MVVM Light Visual Studio extension is installed. I have used the code snippets from this when looking into the NavigationService, the projects are also available as a download from OneDrive.

The Example Code

The code in the BasicNavigation app accompaning this blog post is based upon the MVVM Light Xamarin sample provided by Laurent. The sample demonstrates the projects generated by the MVVM Light New Project templates for Xamarin.iOS and Xamarin.Android.

These projects generate code to demonstrate a number of MVVM Light features including:-
Standard MVVM Light Scaffolding:- ViewModelLocator and MainViewModel
Design Mode:- using ViewModelLocator and DesignDataService
RelayCommand:- including data binding
DispatcherHelper:- used for the RunClock method in the MainViewModel
Messenger:- sending a loosely coupled message
SimpleIoc:- Inversion of Control container included with MVVM Light
Navigation Service:- Cross platform navigation
DialogService:- Cross platform message boxes/dialogs

The Mvvm Light Toolkit documentation pages cover the NavigationService for Xamarin. These use Visual Studio to create a iOS and Android apps demonstrating basic navigation.

The example I worked through is very similar, the main difference’s being to start with a SingleViewApp template in Xamarin Studio and to use View Models to use a more real world example whereby the MVVM Light binding framework would also be used.

One of my goals was to have a simple navigation example which has a software architecture representative of a real world Xamarin MVVM Light application. To this end while the example focuses on the Navigation Service these other features are also incorporated in a minimalistic way:-
Standard MVVM Light Scaffolding classes
RelayCommand,
SimpleIoc
Bootstrapping

As a long time Visual Studio user I’m also trying to focus on using Xamarin Studio natively on a Mac in order to learn how the tools compare.

Wanting to see how to share ViewModel, Model and Services code I opted to create a new solution using the SingleViewApp template in Xamarin Studio and added only the code required to create navigation buttons, bind them to the view model and use the NavigationService to navigate to a second page and then go back.

I omitted using any Navigation Parameters as shown in the example/new project code as I wanted to keep things as simple as possible.

Having read Miguel de Icaza’s recent post on Shared Projects or PCL. I’ve gone down the road of a Shared Project on this occasion, the shared code is for an application rather than for reuse as a framework or library so this seems a good fit.

Key Points

Adding the MVVM Light Nuget package creates MainViewModel and ViewModelLocator classes which can be moved to the Shared Project. Adding the MVVM Light libraries only Nuget package does the same but without the creation of these two classes.

The ViewModelLocator is less useful on Xamarin platforms as the design time data provision is not relevant. In this example a static property is used so that the ViewControllers (iOS) and Activity’s (Android) can access long lived ViewModels from the SimpleIOC container.

The ‘bootstrapping’ of the MVVM Light components is done in the AppDelegate and Application (iOS) and App (Android) classes. This includes initialisation of the DispatcherHelper and the creation of the NavigationService, registration of this with the SimpleIoc container and the configuration of the NavigationService to map key names to pages.

The NavigationService is configured to use a key mapped to a StoryboardId when using iOS storyboards for example:-

nav.Configure(ViewModelLocator.SecondPageKey, "SecondPage");  

The NavigationService is configured to use a key mapped to a type for iOS XIB’s and Android for example:-

nav.Configure(ViewModelLocator.SecondPageKey, typeof(SecondActivity));  

iOS ViewControllers which are a navigation target should derive from the ControllerBase class in the GalaSoft.MvvmLight.Views namespace.

Android Activity’s which are a navigation target should derive from the ActivityBase class in the GalaSoft.MvvmLight.Views namespace.

The MVVM Light binding framework is key to the use of MVVM and these are setup in the ViewController (iOS) and Activity (Android). A reference to these bindings must be kept to avoid them being garbaged collected, in the example they are stored in a List, Android Example:-

[Activity (Label = "BasicNavigation", MainLauncher = true,
 Icon = "@mipmap/icon")]

public class MainActivity : ActivityBase  
{

  // Keep track of bindings to avoid premature garbage collection

  private readonly List<Binding> _bindings = new List<Binding>();


}

iOS example:-

partial class MainViewController : ControllerBase  
{

  // Keep track of bindings to avoid premature garbage collection

  private readonly List<Binding> _bindings = new List<Binding>();


}

The examples use the SimpleIoc Dependency Inversion container which is part of the MVVM Light framework.

Laurent’s example code for Android contains nested partial classes for the Activity’s (named for example SecondActivity.ui.cs) he has a post describing the technique.

These partial classes contain properties for the UI Elements declared in the view, and also derive from the ActivityBase for example:-

public partial class SecondActivity : ActivityBase  
{
  private TextView _navigationParameterText;


  public TextView NavigationParameterText

  {
    get

    {
      return _navigationParameterText ??
               (_navigationParameterText = 
  FindViewById<TextView>(Resource.Id.NavigationParameterText));

    }
  }

  private Button _goBackButton;


  public Button GoBackButton

  {
    get
    {
      return _goBackButton
 ?? (_goBackButton =
 FindViewById<Button>(Resource.Id.GoBackButton));

    }
  }
}

Be aware that an MVVM Light application working in Debug make stop working in Release mode due to the Linker removing events used by the binding framework. Laurent describes the problem and how to fix this in a post Solving the 'Event not found' issue in Xamarin.

The BasicNavigation App

The BasicNavigation app is a very simple example focusing on the basics, it has two pages and demonstrates the use of the NavigationService’s Configure, NavigateTo and GoBack methods. Laurent’s example’s are slightly more complex demonstrating also the use of NavigationParameters and retrieving the current page key.

iOS Main Page

iOS Second Page

Android Main Page

Android Second Page

The example code can be found on GitHub.

The Shared Code - Step By Step

The following instructions detail how to setup the shared project containing the View Model and ViewModelLocator and include snippets/code listings.

The step by step instructions for the iOS and Android projects will form separate posts due to their size.

Using Xamarin Studio create a Single View App for iOS and Android named BasicNavigation.

Choose to use a Shared Project

Project Configuration using Git

The created solution will have three projects:-
BasicNavigation.iOS, BasicNavigation.Droid and the shared project BasicNavigation. It is this shared project into which the common code across both platforms will be placed. This could comprise of View Models, Models and common Service abstractions.

Choose Add Packages to the BasicNavigation.iOS project and search for mvvm light. Choosing either the MVVM Light libraries only or the MVVM Light package are fine.

In this case I will use the MVVM Light package as this will create a folder called ViewModel containing skeleton classes for the MainViewModel and ViewModelLocator.

Now move the ViewModel folder from the BasicNavigation.iOS project to the BasicNavigation shared project. Rename the namespaces to BasicNavigation.ViewModel.

Next add the MVVM Light Libraries only package to the BasicNavigation.Droid project - this time we do not need the MainViewModel and ViewModelLocator classes to be created for each since we are sharing them in the Basic Navigation project.

A Rebuild All should now build both the iOS and Droid projects without error.

Shared View Model code

Open the MainViewModel class and add the using statements:-

using GalaSoft.MvvmLight.Command;  
using GalaSoft.MvvmLight.Views;  

Now edit it to add an INotifyPropertyChanged (INPC) property for the WelcomeTitle and a RelayCommand for the navigation. Also add the NavigationService dependency to the constructor and store it ion a private variable:-

private string welcomeTitle;  
private RelayCommand navigateCommand;  
private readonly INavigationService navigationService;



public MainViewModel(INavigationService navigationService)  
{

  this.navigationService = navigationService;


  WelcomeTitle = "Home Page";

}



public string WelcomeTitle  
{

  get
 { return welcomeTitle;
 }

  set
 {
    Set(ref welcomeTitle, value);
 }

}



public RelayCommand NavigateCommand  
{

  get

  {

    return navigateCommand
 ?? (navigateCommand = 
      new RelayCommand(()
=>navigationService.NavigateTo(ViewModelLocator.SecondPageKey)));

  }

}


Full class listing:-

using GalaSoft.MvvmLight;  
using GalaSoft.MvvmLight.Command;  

using GalaSoft.MvvmLight.Views;



namespace BasicNavigation.ViewModel  

{

  public class MainViewModel : ViewModelBase

  {

    private string welcomeTitle;


    private RelayCommand navigateCommand;


    private readonly INavigationService navigationService;



    public MainViewModel(INavigationService navigationService)

    {

      this.navigationService = navigationService;


      WelcomeTitle = "Home Page";

    }



    public string WelcomeTitle

    {

      get
 {
 return welcomeTitle;
 }

      set
 {
 Set(ref welcomeTitle, value);
 }

    }



    public RelayCommand NavigateCommand

    {

      get

      {

        return navigateCommand
 ?? (navigateCommand = 
new RelayCommand(() =>  
navigationService.NavigateTo(
ViewModelLocator.SecondPageKey)));  
      }

    }

  }

}


Now open the ViewModelLocator class and add the key used by the navigation service for the second page.

public const string SecondPageKey = "SecondPage";  

The ViewModelLocator was originally used in Microsoft XAML based technologies to provide a different set of view models and services for the design time when using using Microsoft Blend or the Visual Studio designer. In Xamarin iOS and Android this designer support is no longer relevant and the class comment states that it provides static references to all the view models and provides an entry point for the bindings. In practice the view models exposed by the ViewModelLocator should only be those which are long lived. further reading on MVVM Light and Inversion of Control (IOC)

Full class listing:-

using GalaSoft.MvvmLight;  

using GalaSoft.MvvmLight.Ioc;  
using Microsoft.Practices.ServiceLocation;  


namespace BasicNavigation.ViewModel  

{

  public class ViewModelLocator

  {

    public const string SecondPageKey = "SecondPage";



    public ViewModelLocator()

    {

      ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);


      SimpleIoc.Default.Register<MainViewModel>();

    }



    public MainViewModel Main

    {

      get
 {
 return ServiceLocator.Current.GetInstance<MainViewModel>();
 }

    }


    public static void Cleanup()

    {

      // TODO Clear the ViewModels

    }

  }

}


This completes the creation of the basic solution with an iOS and Android app and the Shared Project containing the common ViewModel and ViewModelLocator classes.

Please see also the step by step instructions for creating the iOS and Android implementations. The full example code is on GitHub.

Richard Woollcott

Read more posts by this author.

Taunton, United Kingdom