[MVVMbasics] Targeting the Android and iOS platforms via Xamarin.Forms #2

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

Project setup in Xamarin Studio:

When using the Xamarin Starter, Indie, or Academic license (or when using Mac OS), it is not possible to use Visual Studio as IDE, instead you might be forced to use Xamarin Studio for development. In this case, you can basically follow the same steps for setting up the project structure as if you were using Visual Studio, however there are a few items that need special attention:

  • Xamarin Studio doesn’t support the creation of Windows Phone applications. Therefore, the solution won’t contain a WinPhone project.

    I’d strongly recommend to add an additional Portable Class Library (PCL) to the automatically created projects that contains all Data Models, Viewmodels, and Service interfaces. In this case, you can create a separate Windows Phone solution in Visual Studio, add a reference to this PCL project, and create a WinPhone application out of the given Models and Viewmodels. In this case, you are not even restricted to using Windows Phone Silverlight (as you would be if using pure Xamarin.Forms), but the Phone project can also be a WinRT App that also runs on Windows 8 devices. (Of course, in this case the effort is a little higher than with Xamarin.Forms-only project, since the Views and Service implementations must be created individually for the Silverlight / WinRT part.)

  • The use of an additional PCL project that contains Models and Viewmodels, as suggested above, also ensures that the App can be ported to other platforms (e.g., WPF) at a later point in time. Alternatively, this PCL can also be created in Visual Studio as part of a WPF solution, and referenced from Xamarin Studio at a later point in time to create a Xamarin.Forms App that provides the same functionality as the WPF application.
  • The MVVMbasics NuGet package contains PowerShell scripts that need to run during package installation in order to add all necessary assembly references. When adding NuGet references through the visual NuGet Package Manager using Xamarin Studio on Mac OS, these PowerShell scripts are not executed. Instead, I recommend to install the NuGet PowerShell Console and use this add-in for adding the MVVMbasics reference.

    To do so, choose the Package Console Extension item from the View -> Pads menu after the NuGet PowerShell Console add-in has been installed, and type Install-Package MvvmBasics to add the MVVMbasics framework to the current project!

Implementing Views:

When creating pages, make sure to add a new item of type Forms Xaml Page as this will allow you to specify the page’s content in XAML code. All pages that shall be automatically assigned their Viewmodel by the MVVMbasics NavigatorService must be derived from the MVVMbasics.Views.BaseView base class. All pages generated by Visual Studio or Xamarin Studio usually are derived from the Xamarin ContentPage class, so you must adapt each page’s base class in both C# and XAML code.When referencing the MVVMbasics.Views namespace in XAML, note that it is defined within the MVVMbasicsXF assembly:

xmlns:views="clr-namespace:MVVMbasics.Views;assembly=MVVMbasicsXF"

The MVVMbasics.Views.BaseView class itself inherits from Xamarin.Forms.ContentPage, so you may design the page’s content as if it was a default ContentPage. The creation of other Xamarin page types (e.g., TabbedPage, CarouselPage, …) is not supported by MVVMbasics at the moment, however the MVVMbasics framework provides an alternative for using NavigationPages as shown in the following section Implementing the global App class.

In addition, the MvvmNavigationTarget attribute should be added to each View class, as this enables the automatic assignment of Viewmodels to View. In summary, a sample MVVMbasics page could be implemented as follows:

<?xml version="1.0" encoding="utf-8" ?>
<views:BaseView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:MVVMbasics.Views;assembly=MVVMbasicsXF"
             x:Class="MyApp.Views.MyPage">
	<Label Text="{Binding DisplayText}"/>
</views:BaseView>
using Core.Viewmodels;
using MVVMbasics.Attributes;
using MVVMbasics.Views;

namespace MyApp.Views
{
	[MvvmNavigationTarget(typeof(MyViewmodel))]
	public partial class MyPage : BaseView
	{
		public MyPage()
		{
			InitializeComponent();
		}
	}
}

Implementing the global App class:

Each Xamarin.Forms application contains one global App.cs class file, which is instantiated and started during App startup by the various platform-specific projects. When using MVVMbasics, this App class must be derived from the MVVMbasics.BaseApplication base class. This one itself inherits from Xamarin.Forms.Application, which means that inside your App class you can do whatever you are used to from any other Xamarin.Forms applications, e.g. override the OnSleep() and OnResume() methods.

Within the App class’ constructor, you may register all desired MVVM services to the global ServiceLocator, as is the case in all MVVMbasics applications on other platforms. The only major difference to a typical Xamarin.Forms App class is that instead of assigning the App’s startup page to the MainPage property, you call the SetStartupPage method. This method expects the App’s startup page either as type parameter (in which case it is automatically instantiated) or as parameter (if it has been instantiated already):

SetStartupPage<MyPage>();
SetStartupPage(new MyPage());

Internally, the SetStartupPage method instantiates the provided page if necessary and assigns it to the App’s MainPage property. In addition, it checks whether the MVVMbasics NavigatorService has been registered and if it contains more than one View / Viewmodel pair – in this case it can be assumed that the App shall support page navigation, and the startup page is automatically wrapped within a Xamarin.Forms.NavigationPage. This means that there is no need to manually create an instance of NavigationPage!

In summary, the full implementation of an MVVMbasics App class for Xamarin.Forms could look as follows:

public class App : BaseApplication
{
	public App()
	{
		// Services used by the application
		var navigationService = new NavigatorService();
		navigationService.RegisterAll("MyApp.Views.*");
		ServiceLocator.Register(navigationService);
		ServiceLocator.Register<MessageboxService>();

		// The root page of the application
		SetStartupPage<MyPage>();
	}
}