1 Comments

These days if you can write code with C# you can write code for Windows, Linux and OSX, your code can run on Desktop, Server, Mobile or Embedded Devices. So C# runs pretty much everywhere which if you are a C# developer is a great thing! Smile Only little hiccup, even though C# is a standardised language, there are multiple runtimes existing today on which C# runs. This may lead to the assumption of having to rewrite code for every runtime. As the standard .Net C# library can not be reused on a Silverlight runtime, or the new Windows RT runtime, or I think you get the message. But fear not – thanks to the Portable Class Library (PCL) one is able to write code that can be reused over multiple platforms.

Portable Class Libraries

When adding a Portable Class Library (PCL) you will have to choose which platforms you want to use the platform on. The supported platforms have an impact in the functionality the PCL provides without adding any additional libraries (usually via NuGet). You can find a list  of libraries supported by each platform on MSDN.

For this post we will want to reuse our code on the following platforms:

  • Universal Windows App (Windows 10)
  • Classic desktop WPF app
  • iOS (with Xamarin)
  • Android (with Xamarin)

To keep things simple the logic in the app will be creating a list of people. We will even be able to share our view models from the PCL so the only overhead we will be having when creating the app is the actual UI code and wiring up the view models to the actual views. Now in this setup the timesaving's might seem marginal but think about your standard business app and the savings will start to up add up quickly in a major way.

Creating a PCL

Adding the platform specific projects is pretty straight forward. Simply add the corresponding project template to the solution when adding a new project, so I’ll leave it at that and go over to adding a PCL. When adding the PCL a dialog will be opened offering to choose the platforms that shall be supported i.e. can consume the PCL.

Showing Add Portable Class Library Visual Studio dialog with .Net Framework 4.6, Windows Universal 10.0, Xamarin.Android and Xamarin.iOS selected

The iOS and Android option will show up after installing the Xamarin tool chain.

With the platforms chosen we can now start implementing the “business logic” which in our case is a simple generator that we invoke, called PersonService.cs:

public class PersonService
{
    public async Task<IEnumerable<Person>> GetPeople(int count = 42)
    {
        var people = new List<Person>(count);
        // In case of large counts lets be safe and not run this on the UI thread
        await Task.Run(() =>
        {
            for (int i = 0; i < count; ++i)
            {
                people.Add(new Person{FirstName = NameGenerator.GenRandomFirstName(), LastName = NameGenerator.GenRandomLastName()});
            }
        });

        return people;
    }
}

To present our data to the UI we will use the MVVM pattern.

Adding MVVM Light

When using MVVM in a project (which is like always for me Winking smile) I prefer using MVVM Light. MVVM Light can be added by simply installing a NuGet package:

PM> Install-Package MvvmLightLibs

As we will access the view models from the platforms make sure to add the MVVM Light libraries also to the platform specific code bases.

Now we can add the view model MainViewModel.cs that will hold the list of people we will display.

public class MainViewModel:ViewModelBase
{
    private readonly IPersonService _personService;

    public MainViewModel(IPersonService personService)
    {
        if (personService == null) throw new ArgumentNullException(nameof(personService));
        _personService = personService;
        if (IsInDesignMode)
        {
            People = new ObservableCollection<Person> {new Person{FirstName = "Doctor Who"}, new Person {FirstName = "Rose", LastName = "Tyler"}, new Person {FirstName = "River", LastName = "Song"} };
        }
        else
        {
            People = new ObservableCollection<Person>();
        }
    }

    public ObservableCollection<Person> People { get; set; }

    public async Task InitAsync()
    {
        var people = await _personService.GetPeople();
        People.Clear();
        foreach (var person in people)
        {
            People.Add(person);
        }
    }
}

Next we still need to configure the ViewModelLocator.cs, which allows us to easily manage dependencies.

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<IPersonService, PersonService>();
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel MainViewModel => SimpleIoc.Default.GetInstance<MainViewModel>();
}

So now we have all of our cross platform code setup. Let’s get it running on our desired targets.

The platforms

On the platforms we can simple reference the PCL like any other library we might use and access the features. On our platforms we will have to do the following steps:

  1. Create the UI
  2. Hook up theViewModelLocator.cs
  3. Wire up the view model to the view

Let’s do these steps for the Universal Windows App.

Universal Windows App (UWA)

For the view we will simply add a ListView to the MainPage.xaml:

<Page
    x:Class="PclSample.UWA.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclSample.UWA"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="..."
    mc:Ignorable="d">

    <ListView ItemsSource="{Binding People}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}"/>
                <TextBlock Text="{Binding LastName}"/>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Page>

Under Windows (this is also true for WPF) MVVM Light really integrates really nicely. The Locator we can simply add to the App.xaml:

<Application
    x:Class="PclSample.UWA.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclSample.UWA"
    RequestedTheme="Light">
    <Application.Resources>
        <vm:ViewModelLocator x:Key="Locator" xmlns:vm="using:PclSample.Core" />
        <ResourceDictionary />
    </Application.Resources>
</Application>

This allows us to access properties from the ViewModelLocator.cs class within our view(s) i.e. MainPage.xaml. So the next step would be wiring up the view model to the views DataContext, which will populate the view:

<Page
    x:Class="PclSample.UWA.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PclSample.UWA"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Source={StaticResource Locator}, Path=MainViewModel}"
    mc:Ignorable="d">

    ...
</Page>

Now all is set and we can enjoy the view of our light weight UWA.

Screenshot of the UWA running in the Windows 10 Mobile Emulator

Windows Presentation Foundation (WPF)

Following the same steps as in the UWA in a WPF app will lead to the same result.

Shows sample app running in as a WPF desktop application

So we can reuse all of our business logic from one Microsoft client development model to an other one. Isn’t that just great? Smile But wait there is more. We can take the C# code outside of the Microsoft Ecosystem. With for example Xamarin we can reuse our C# code on iOS and Android.

iOS

Under iOS the UI is usually created in a designer (similar to Windows Forms) so there is not much code to show. We add the ListView equivalent from iOS a UITableView to a page and give it a name, in this sample PeopleTableView.

Showing iOS Designer and where the name of the UITableView is set.

Setting up the ViewModelLocator.cs is not quite as elegant when we leave the Microsoft platforms but then again it is done just as easily. In the AppDelegate.cs which is the start up point of every iOS app we simply create an Instance of the ViewModelLocator.cs and store it in a property. The property then can be accessed throughout the iOS app. The Wiring up of the view model is done in the ViewController.cs which is linked to the view that we setup earlier:

public partial class ViewController : UIViewController
{
    ObservableTableViewController<Person> _tableViewController;

    public ViewController (IntPtr handle) : base (handle)
    {
    }

    private MainViewModel Vm => Application.Locator.MainViewModel;

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        // Perform any additional setup after loading the view, typically from a nib.

        _tableViewController = Vm.People.GetController(CreatePersonCell, BindPersonCell);
        _tableViewController.TableView = PeopleTableView;
    }

    public override async void ViewWillAppear (bool animated)
    {
        base.ViewWillAppear (animated);
        await Vm.InitAsync();
    }

    public override void DidReceiveMemoryWarning ()
    {
        base.DidReceiveMemoryWarning ();
        // Release any cached data, images, etc that aren't in use.
    }

    UITableViewCell CreatePersonCell (Foundation.NSString reuseId)
    {
        var cell = new UITableViewCell(UITableViewCellStyle.Default, null);
        return cell;
    }

    void BindPersonCell (UITableViewCell cell, Person person, Foundation.NSIndexPath path)
    {
        cell.TextLabel.Text = person.FullName;
    }
}

Now all that is left to do for us is again fire up the iOS Simulator to verify all is correct and there we have it, the same C# code we used for our WPF and UWA apps is now running under iOS:

iphone

Android

What we did under iOS we can also replicate under Android. Though not part of the Microsoft eco system the model should be more familiar if you have written WPF, Modern Apps (and all the other fancy names they had i.e. Universal Apps). Under Resources/Layouts there is the main.axml which is a (Application) XML file we can edit to tell the Android OS how to render the UI. Sounds a bit like XAML right? And the concepts do overlap in some parts too. Adding a ListView to the XML and set the id of the element which will allow us to access it later on:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/PeopleListView" />
</LinearLayout>

Again we will have to setup the locator. Under Android there is no fixed setup point, so we will use a static class Locator.cs and property which we will access from the Android app:

internal static class Locator
{
    private static readonly Lazy<ViewModelLocator> _locator = new Lazy<ViewModelLocator>(() => new ViewModelLocator());
    public static ViewModelLocator Instance => _locator.Value;
}

Wiring up the view model is done in the MainActivity.cs, which you can think of as the code behind/ViewController equivalent. I wrote about this binding in more detail in a former blog post which you can find here.

[Activity(Label = "PclSample.Droid", MainLauncher = true, Icon = "@drawable/icon")]
internal class MainActivity : Activity
{
    protected override async void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);

        await Vm.InitAsync();

        // Get our button from the layout resource,
        // and attach an event to it
        PeopleListView.Adapter = Vm.People.GetAdapter(GetPersonView);
    }

    public ListView PeopleListView => FindViewById<ListView>(Resource.Id.PeopleListView);

    private MainViewModel Vm => Locator.Instance.MainViewModel;

    private View GetPersonView(int position, Person person, View convertView)
    {
        View view = convertView ?? LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);

        view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = person.FullName;

        return view;
    }
}

Note that the id we previously set allows us to retrieve the UI control.

At this point we can start up the Android Emulator and just to have mentioned it Visual Studio 2015 provides a great Android Emulator – way better then the stock emulator! And once again we can see the app is running reusing the C# code we tucked away in our PCL.

Shows app running in the Android Emulator

Conclusions

In this blog post we saw how one can share C# code with a Portable Class Library (PCL). The PCL can be included in all major C# stacks .Net, UWP, Silverlight, Xamarin etc. and though the capabilities in the PCL are more limited then a standard .Net library it does allow to share code from a legacy WPF/Win Forms app to a mobile application.

PCLs can be extended by installing further NuGet packages such as storage, network access and many more. The PCL has been around for a couple of years now and has proven itself to be a valuable component when writing cross platform applications.

The entire sample can be found on GitHub.

3 Comments

Screenshot_2015-10-02-08-41-47

This is an extension to a previous post that describes how to create bindings for controls. In this post we will look at how to bind a collection to a Android ListView and update the View every time an item is added or removed from the collection in the View Model.

Project Setup

Add the MVVM Light libraries from Laurent Bugnion via NuGet to a Xamarin.Android project:

PM> Install-Package MvvmLight

Then in the View Model create an ObservableCollection which will represent the entire List.

public ObservableCollection<Person> People { get; private set; }

To setup the list we can use an Initializer method, which is currently generated in a separate thread. Now this only makes sense when the list is large i.e. processor heavy which this creation can be if we start jacking up the number. So with the basics all set lets turn our attention to the Activity.

Activity

The ideal place to setup bindings is in the OnCreate method, so by overriding it we can setup the binding for the list. The data container of an Android ListView is the Adapter which we usually have to create by hand. Thanks to MVVM Light we can do this in one line of code:

protected override async void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    SetContentView(Resource.Layout.Main);

    await Vm.InitAsync();
    PeopleListView.Adapter = Vm.People.GetAdapter(GetPersonView);
    // ...
}

The GetPersonView parameter is a method that gets invoked when a displayed row is created. In this method the data of the row is filled accordingly into the UI fields:

private View GetPersonView(int position, Person person, View convertView)
{
    View view = convertView ?? LayoutInflater.Inflate(Resource.Layout.RowPerson, null);

    var firstName = view.FindViewById<TextView>(Resource.Id.FirstName);
    var lastName = view.FindViewById<TextView>(Resource.Id.LastName);

    firstName.Text = person.FirstName;
    lastName.Text = person.LastName;

    return view;
}

Note that the YYY parameter might contain a row that can be reused. As only a certain amount of rows can be displayed at a time rows become obsolete after the user has scrolled them to far out of view. These rows are then passed in as the parameter YYY which is then not null and the fields can be updated with new data. Resulting in a smaller memory footprint which is always good on memory constrained mobile devices.

View

The layouts are simple. For the Activity a simple LinearLayout is used with a ListView within it:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/People" />
</LinearLayout>

The row contains two TextFields that are used to display the persons first and last name.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="5dp">
    <TextView
        android:text="Michael"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/FirstName"
        android:layout_margin="5dp" />
    <TextView
        android:text="Westen"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/LastName"
        android:layout_margin="5dp" />
</LinearLayout>

The row layout is then inflated in the GetPersonView method.

Adding and removing people from the ListView

Adding and removing people from the collection is now really simple. So all we need to extend our view by are two buttons:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/AddButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/AddPerson" />
        <Button
            android:id="@+id/RemoveButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/RemovePerson" />
    </LinearLayout>
    <!-- ... -->
</LinearLayout>

Then wiring them up in the Activity to Commands in the View Model.

protected override async void OnCreate(Bundle bundle)
{
    // ...

    AddPersonButton.SetCommand("Click", Vm.AddPersonCommand);
    RemovePersonButton.SetCommand("Click", Vm.RemovePersonCommand);
}

In the View Model we simply have two Relay Commands which are initialized in the Constructor:

public MainViewModel()
{
    AddPersonCommand = new RelayCommand(AddPerson);
    RemovePersonCommand = new RelayCommand(RemovePerson);
}

public RelayCommand AddPersonCommand { get; set; }
public RelayCommand RemovePersonCommand { get; set; }

When invoking the commands a person is added or removed from the observable collection which will automatically will be propagated to the presentation in the ListView.

Be aware of the Activity Lifecycle

Note there is a possibility of a memory leak when it comes to the adapter provided by MVVM Light, this has to do with an internal setup of how the Adapter is created. When the Activity is destroyed and recreated e.g. when you turn the device and change the orientation. Internally the activity will be hooked to an event of the observable collection in the View Model. This connection will last even after a new activity is created. Therefore the old activity still hangs around as it is always hooked to the Observable collection in the View Model. This is why in the View Model on every InitAsync the Observable Collection will be replaced with a new instance. This will clean up the trail and allow the no longer used Activity to be garbage collected.

public async Task InitAsync()
{
    if (People != null)
    {
        // Prevent memory leak in Android
        var peopleCopy = People.ToList();
        People = new ObservableCollection<Person>(peopleCopy);
        return;
    }

    People = new ObservableCollection<Person>();

    var people = await InitPeopleList();
    People.Clear();
    foreach (var person in people)
    {
        People.Add(person);
    }
}

Conclusion

In this post we saw how we can bind a collection to a ListView and how updates to the collection are automatically propagated to the view. Further we saw how to handle the lifecycle of an Activity properly without generating a memory leak. Thanks to MVVM Light the complexity displaying collections in an Android app are greatly reduced.

 

The entire sample can be found under GitHub.

This post was previously posted on the Noser Engineering Blog.

0 Comments

TitleImage

Writing Unit, Component and Integration tests allows to test functionality of software modules. In other words letting developers sleep tightly without worries at night. These tests run against certain parts of the code verifying the logic and interaction between modules of the app. All this is usually performed on the developers machine powered by a beefy processor and often unheard amount of RAM when it comes to mobile devices. Wouldn’t it be great if we could get a bit closer to the real thing? Well we can…

In this blog post we will look at how we can run xUnit.net tests on a device. The app will be a Xamarin(.Forms) app, which consists of three platform projects and a shared Portable Class Library which can be used to write logic that can be consumed on every platform.

Setting up xUnit.net

The typical xUnit.net tests are created in a standard .Net library. All that is required is the xUnit.net NuGet package:

PM> Install-Package xunit -Version 2.0.0

Now we can create start writing unit tests, for this blog post let’s stick to the basic calculator example in the BasicMathServiceTest.cs:

public class BasicMathServiceTest
{
    private BasicMathService _basicMathService;

    public BasicMathServiceTest()
    {
        _basicMathService = new BasicMathService();
    }

    [Fact]
    public void Add_GivenTwoNumbers_TheSumIsReturned()
    {
        var x = 35;
        var y = 7;
        var expectedResult = 42;

        var result = _basicMathService.Add(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void Subtract_GivenTwoNumbers_TheSubtractedResultIsReturned()
    {
        var x = 456;
        var y = 123;
        var expectedResult = 333;

        var result = _basicMathService.Subtract(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void Mulitply_GivenTwoNumbers_TheResultIsReturned()
    {
        var x = 2;
        var y = 2;
        var expectedResult = 4;

        var result = _basicMathService.Multiply(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void Divide_GivenTwoNumbers_TheSumIsReturned()
    {
        var x = 848;
        var y = 8;
        var expectedResult = 106;

        var result = _basicMathService.Divide(x, y);

        Assert.Equal(expectedResult, result);
    }

    [Fact]
    public void TheFailingTest()
    {
        var x = 4;
        var y = 2;
        var expectedResult = 8;

        var result = _basicMathService.Add(x, y);

        Assert.Equal(expectedResult, result);
    }
}

The code that we test against lives in a PCL and performs the calculations. Now let’s take these existing tests and execute them on the simulator or even a real device.

Running Tests on devices

For this first add the platforms on which the project will run. Now add the following xUnit.net NuGet package:

PM> Install-Package xunit.runner.devices -Version 1.0.0

Written by Oren Novotny whom we have to thank for enabling xUnit.net on Android, iOS and Windows Phone! This package will automatically add the xUnit.net and other dependencies required for running tests on your devices according to the platform to which it’s being added. Depending on the platform the xUnit.net for Devices package adds different template files as text files:

  • Android
    • MainActivity.cs.txt
  • iOS
    • AppDelegate.cs.txt
  • Windows Phone
    • MainPage.xaml.txt
    • MainPage.xaml.cs.txt

Simply replace the content of their default counterparts e.g. for iOS replace the AppDelegate.cs with the content of the App.Delegate.cs.txt (and thanks to some extra effort by Oren Novotny even the namespaces will just simply match Smile). Now you could simply start adding new class files and write out tests. The runner will automatically find them via reflection (even if you place them in subfolders).

Using existing tests

What is probably a more useful approach is to simply reuse existing tests. This is why in a next step lets see how we can add the unit test file BasicMathServiceTest.cs without creating a duplicate dopy. Simply right click on the Project then Add/Existing Item… browse to the unit test file and add it as link.

Shows the dropdown on the Add button that can be used to add a file as a link.

As a link to the file is simply a pointer to the original we only have to maintain one unit test file and all the links will automatically “update” as they simply reference the original.

Now the Project can be set as startup project and executed on the device. Bellow you see some sample screenshots from an iOS Emulator.

TestOverview

You can even dig into the error messages and see what went wrong during a test.

TestDetails

Conclusion

In this post we saw how to create and reuse xUnit.net tests on devices for iOS, Android and Windows. This can be very powerful when we have to test certain features on a device for example does this work with AOT on iOS? Or simply running integration tests on a real device, giving valuable insights and further allowing to tests performance, latency and so on.

This post focuses on xUnit.net and also shows one of it’s many strengths on the capabilities that can be easily added. The same can be done with NUnit which may be your testing framework of choice and which Xamarin provides project templates to run the tests on a device.

You can find the sample code on GitHub.

0 Comments

Android logo portraied in stack of squares with rounded edges.

In this weeks blog post we will look at how we can remove an Activity from the Navigation Stack. This can be very useful if your are implementing an extended splash screen and don’t want to navigate back to it when the user selects the back button.

For this we will first create a welcome screen which will navigate to the main activity, in the process it will remove the welcome screen i.e. the activity behind from the navigation stack allowing the user to quit the app from the main screen.

Creating a welcome screen

For the welcome screen we will create a normal linear layout page, so nothing special here. For navigating to the main activity we create an intent and configure it to create the target activity in a new task:

var intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(ActivityFlags.NewTask);
StartActivity(intent);

After navigating to the main activity we call the Finish method which will terminate the WelcomeActivity and remove it from the navigation stack.

Finish();

We can place the code in the on created method as such:

[Activity(Label = "RemoveActivityFromNavigationstack", MainLauncher = true, Icon = "@drawable/icon")]
public class WelcomeActivity : Activity
{
    protected override async void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        SetContentView(Resource.Layout.Welcome);

        // Do some meaninthing stuff here, or just wait for 3 seconds...
        await Task.Delay(3000);

        var intent = new Intent(this, typeof(MainActivity));
        intent.SetFlags(ActivityFlags.NewTask);
        StartActivity(intent);
        Finish();
    }
}

Note that if the ActivityFlags.NewTask is not set, the targeted activity will also stop running and the user will only see a blank screen of the app.

Conclusion

We saw how to setup navigation to remove an activity from the navigation stack. This method is ideally used when removing an extended splash screen or the like from the navigation stack allowing the user to close the app from the root screen.

You can find the entire sample on GitHub.

0 Comments

androidMvvmLight

This week we’ll have a look at how we can use the MVVM pattern on Xamarin.Android using the MVVM Light framework from Laurent Bugnion.

Creating the View

For this sample lets create a basic entry view with an EditText, Buttonand TextView to display the entry that was submitted via the button.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <EditText
        android:id="@+id/MessageText"
        android:hint="@string/MessageTextHint"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/SubmitMessage"
        android:layout_marginBottom="10dp"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/SubmitMessage" />
    <TextView
        android:id="@+id/SubmittedMessage"
        android:layout_marginBottom="10dp"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/SubmittedMessageText" />
</LinearLayout>

As you can observe this is a standard LinearLayout containing default Android controls. With MVVM Light we do not have the option as in MVVM Cross to set the binding code directly in the AXML but more how it’s done later. So lets setup the corresponding ViewModel.

Creating the ViewModel

With in the ViewModel we need a property to store the entered message, another one to expose an ICommand which we can bind to the button and finally a third property where we can store the message that was entered at the time the button is being pushed:

public class MainViewModel : ViewModelBase
{
    private string _message;
    private string _previousMessage;

    public MainViewModel()
    {
        MessageCommand = new RelayCommand<string>(SubmitMessage);
    }

    public RelayCommand<string> MessageCommand { get; private set; }

    private void SubmitMessage(string message)
    {
        PreviousMessage = message;
    }

    public string PreviousMessage
    {
        get { return _previousMessage; }
        set
        {
            _previousMessage = value;
            RaisePropertyChanged(propertyName: nameof(PreviousMessage));
        }
    }

    public string Message
    {
        get { return _message; }
        set
        {
            _message = value;
            RaisePropertyChanged(propertyName: nameof(Message));
        }
    }
}

If you have been using ViewModels before you will not notice anything out of the ordinary with this code which means you could reuse this ViewModel for a WPF, Windows 8, UWP apps or even Xamarin.iOS i.e. Xamarin.Forms app. (This is good Winking smile)

Setting up the Locator

Another step we want to make is to ensure that the ViewModel and any future services will be created and setup over the Inversion of Control container. MVVM Light provides us the SimpleIoC container which usually is setup in the ViewModelLocator.cs class. Currently we only use one view model so that is all we have to setup:

public class ViewModelLocator
{
    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
    }
}

As there is no fixed starting point in Android we have not Main method or such to configure our container on startup. I personally like the idea of a lazy container such in one that is only created when it is really used. So lets create an App.cs class in the root of our Android project. In this class we will instantiate the locator and provide access to this one instance:

public static class App
{
    private static ViewModelLocator _locator;

    public static ViewModelLocator Locator => _locator ?? (_locator = new ViewModelLocator());
}

Now that we have all the basics covered lets move on to the juicy part of wiring up the bindings.

Setting up the bindings

We have to manually set the bindings in the activity for the corresponding view. In this sample app we will do it in the MainActivity.cs. First we wire up the EditText:

_messageBinding = this.SetBinding(() => EditMessage.Text, BindingMode.TwoWay);

The command with the button:

MessageButton.SetCommand("Click", Vm.MessageCommand, _messageBinding);

And the TextViewto the PreviousMessage property:

_textViewBinding = this.SetBinding(() => Vm.PreviousMessage, () => PreviousMessage.Text);

Now whenever we edit a text and select the button the text will appear on the TextView bellow.

Conclusion

In this post we saw how we can create a simple form application and write & read from a ViewModel. We further saw how we can setup the dependency injection module for a Xamarin.Android application and ensure that even if the app should be started with a different activity the container is setup correctly.

You can find the entire little sample project up on GitHub.

References

MVVMLight flowers sample by Laurent Bugnion.