Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Xamarin

Introduction to Mvvmcross Platform

4.33/5 (7 votes)
3 Jun 2015CPOL7 min read 32.9K  
In this article I will give you a brief overview on the basic concepts of mvvmcross platform. We we'll explore the mvvmcross project architecture and some mvvmcross classes.

Introduction

Mvvmcross is a MVVM platform that solves a lot of issues that you will face sooner or later while developing for cross platforms (such as Android, Windows Phone or IOS).

The problem is, that every platform has its own specifications, that's why you cannot simply write one code and run it on multiple platforms as is. That’s where Xamarin becomes very handy.

The main feature of mvvmcross is that you are separating your logic not only from the views (as in MVVM and MVC patterns), but from specific platform implementation.

Your business logic will be implemented in your PCL (Portable Library Class), and each platform can reference it as its logic, while implementing its native side accordingly.

Check out the mvvmcross manifesto:

https://github.com/MvvmCross/MvvmCross/wiki/The-MvvmCross-Manifesto

Mvvmcross on Github:

https://github.com/MvvmCross/MvvmCross

*In this specific example I'll show mvvmcross implementation on Windows 8.1 Store App application.

MVVM Pattern

Those that are familiar with MVC pattern can find it similar to MVVM, since its intended to solve the same problem, but in a slightly different way.  

While MVC separates the program to three modules: View, Controller and Model, the MVVM couples the View and its logic by matching View to appropriate ViewModel. It makes your software design much more flexible, since the only dependency between the View and the ViewModel is established by Binding.

Hardcoded dependency of the view and code logic, (as used in codebehind approach) limits your application dynamics, since your view and code are coupled in a straight way.

For those that are completely new to that concept, I suggest you visit these links:

http://en.wikipedia.org/wiki/Model_View_ViewModel

http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Why MVVM?

Once you designed your application as MVVM, you can simply replace one view with another only by keeping the Binding convention, without touching the logic.

Vice versa, you can switch between ViewModels of the View without touching the View.

That is much harder (almost impossible) to achieve while using the codebehind approach.

In our example we are using the MVVM pattern, but in addition we are separating the logic from the specific application to the PCL library. That will give us the ability to use the same library on different platforms (such as Android, IOS and Windows Phone on Xamarin).

Installing the mvvmcross nugget 

Search for mvvmcross in the "Manage Nugget Packages" window, make sure to install it on both your PCL and you application project.

Image 1

Or, simply type:

PM> Install-Package MvvmCross.HotTuna.Plugin.All -Version 3.2.2

In your Package Manger Console.

As the nugget finishes its installation, notice that you have two new directories named "ToDo-MvvmCross" in your PCL and the application Project, follow the instructions step by step.

If you done everything right, you can compile and run your application. You should end up with something like this:

Image 2

Exploring the mvvmcross project structure

 

Portable Library (PCL)

App.cs 

This is the main class of your PCL, it derives from MvxApplication and it will be instantiated once, as your library created.

Initialize() method

C#
public override void Initialize()
{
    CreatableTypes()
        .EndingWith("Service")
        .AsInterfaces()
        .RegisterAsLazySingleton();
    RegisterAppStart<ViewModels.FirstViewModel>();
}

This method will iterate on all your classes in the library project and each one that ends up with "Service" convention, will be instantiated as singleton using lazy instantiation in your Mvx object.

Of course, you could do it manually:

C#
//Using Func
Mvx.RegisterType<TestService>(() => new TestService());
//using Interface as identifier
Mvx.RegisterSingleton<ITestservice>(new TestService());


You can change the Initialize method as you please.

For instance:

C#
CreatableTypes()
    .EndingWith("Handler")
    .AsTypes()
    .RegisterAsLazySingleton();

Explanation: Now it will traverse on all classes with "Handler" ending and using lazy instantiation, will register them as Types, not as Interfaces.

Notice as well that we are specifying the ViewModel with which our application will start.

C#
RegisterAppStart<ViewModels.FirstViewModel>();

 

Dependency Injection/ IOC in mvvmcross

Dependency injection is a software design pattern in which one or more dependencies are injected, or passed by reference while resolving an object Type.

 

Registering Types and Interfaces

In mvvmcross the Mvx class has three ways to register objects:

RegisterType – Registers the type, by the Interface or by constructor, depending on the overloading function that you choose.

RegisterSingleTone – Registers the object as singleton (only one instance for the whole application life time).

LazyConstructorAndRegistersingleTon – Will register the object as single tone, with lazy constructor instantiation. Which means, that only when calling the Resolve() method of Mvx class – the object will be instantiated.

In mvvmcross there is a class called Mvx, that uses IOC to register and to resolve dependencies.

 

Resolving Types and Interfaces

You can resolve registered objects only by Resolve() method, by specifying a type or interface.

It is recommended to use first CanResolve method or TryResolve to ensure that you will not get a nasty exception thrown.

After you registered your types to the Mvx class using the CreateTypes method or manually, you can now access those classes from any location in your application:

var filehandler = Mvx.Resolve<IFileHandlerAsync>();

 

For more information see those links:

IOC - http://en.wikipedia.org/wiki/Inversion_of_control

DI - http://en.wikipedia.org/wiki/Dependency_injection

 

ViewModels Directory

Another component that is added automatically by the mvvmcross nugget is the ViewModels directory in your library project.

That's where all your ViewModel classes (which derives from MvxViewModel) are stored and will be linked with the Views in your application project by the name convention.

Notice that by default, mvvmcross nugget creates FirstViewModel.cs class in your ViewModels directory, which is linked to FirstView.cs in Views directory in your application project eventually.

The name convention is:

View Convention: [name of the view].cs 

ViewModel Convention: [name of the view]Model.cs

 

MvxViewModel and MvxWindowsPage

When using mvvmcross you will be dealing with Mvx classes, each ViewModel class derives from MvxViewModel, and each View derives from MvxWindowsPage.

While sticking to the MVVM pattern, we are not going to write any codebehind in our View class, so the whole logic of the view will be implemented in the appropriate ViewModel.

MvxViewModel methods

public virtual void Start()

Init() is the first method that’s called in the ViewModel.

C#
public void Init(IMvxBundle parameters)

Start() is called after Init() method, the IMvxBundle parameter is an object where the passed data from previous ViewModel are passed as Key-Vaule pairs, using Dictionary as data structure.

All the passed data are stored as strings, so in order to use it with a complex object you will need to perform a serialization which can seriously harm your performance.

Usually when dealing with complex object another help class is used for those purposes.

C#
public void Init(IMvxBundle parameters);
protected virtual void InitFromBundle(IMvxBundle parameters);
protected virtual void ReloadFromBundle(IMvxBundle state);
public void ReloadState(IMvxBundle state);
public void SaveState(IMvxBundle state);
protected virtual void SaveStateToBundle(IMvxBundle bundle);

Those method are used for storing and reloading data from the bundle. Usually used when your application went to the background and you are interested in saving some data, that can be lost, since the ViewModel will be reinitialized.  The saved data will be read and dealt as the ViewModel reloads, when the application is back to the front.

The call Order:

On ViewModel Create:

  1. Constructor () 
  2. Init()
  3. InitFromBundle()
  4. Start()

On ViewModel Destroy:

SaveStateToBundle()

 

Application Project

In our application project we got a new directory called Views, DebugTrsace.cs class and Setup.cs .

DebugTrace

Derives from IMvxTrace interface , which implement 3 methods:

C#
void Trace(MvxTraceLevel level, string tag, Func<string> message);
void Trace(MvxTraceLevel level, string tag, string message);
void Trace(MvxTraceLevel level, string tag, string message, params object[] args);

Using System.Diagnostics.Debug class for log purposes.

Setup

This is where the application’s setup occur.

These are the methods:

C#
public Setup(Frame rootFrame) : base(rootFrame)
protected override IMvxApplication CreateApp()
protected override IMvxTrace CreateDebugTrace()

Setup - the constructor of the Setup class.

CreateDebugTrace – called when creating DebugTrace, by default – simply returns the DebugTrace class instance.

CreateApp – called right before the whole application is initialized and the connections of the mvvmcross components are established. Here you can register to IOC from the application project and use those objects in the PCL with Mvx class.

For example, if you want to call a DialogMessage object from your ViewModel in the portable library, you cannot establish it by calling the class directly.Since your project does not have the appropriate Assembly reference for that.

In this case, you can create your class that implement some kind of functionality and register it at the shared Mvx (IOC) object, right before the CreateApp method is completed:

C#
protected override IMvxApplication CreateApp()
{
       Mvx.RegisterSingleton<IMessageBox>(new MessageBoxHandler());
       return new Core.App();
}

Declare the interface in the PCL project so that both projects will be familiar with it.

In the ViewModel simple call Resolve method of Mvx class for the desired object instance:

C#
Mvx.Resolve<IMessageBox>().ShowMessage(COMMENT_SUBMIT_SUCCESS);

Now you got your DialogMessage functionality in your ViewModel.

Views

In your xaml View, you can see that the base xaml node is no longer a Page, it is views:MvxWindowsPage which is a mvvmcross type, the code behind is also deriving from the same class.

Now you can create your view and bind the controls to the ViewModel(which is placed in the PCL).

Summary

Mvvmcross is a very convenient platform for developing cross platform applications, it makes your development process much simpler.

Continue reading about mvvmcross plugins, and extensions. There is much more to explore.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)