It is part of a series of posts investigating how to use the MVVM pattern on the Xamarin platforms using shared View Models/Models/Services.

Overview

In this post we start to implement the Android version of the app. The application will present a list of Todo Tasks using MVVM Light to bind from an ObservableCollection in the ViewModel to a ListView. The tasks are held in memory and can be created using a button on the Toolbar.

The app we create here has parity with the iOS version except for the swipe to delete feature. I will cover that in a future post so as to keep the length of this post more manageable. The iOS and Android versions of the app are shown below:-

The main focus of the post is to use the ObservableAdapter provided by MVVMLight to bind the ListView to the ViewModel's ObservableCollection.

Key Points

Binding an Android ListView to an ObservableCollection such that it automatically add and removes items from the list as the ObservableCollection is modified is straight forward. It requires essentially a call to an extension method GetAdapter to create the ObservableAdapter and implementation of a method to provide the View for each row:-

The GetAdapter extension method can be found in the MVVM Light source code in the Galasoft.MvvmLight.Platform (Android) project. Another method is provided for using an IList<T> as the data source. It is responsible for creating an ObservableAdapter and initialising it to use the ObservableCollection and the method providing the View for each row. It's in the folder Helpers defined in the ExtensionsAndroid class and is defined thus:-

This example uses a custom Layout defined in the TaskTemplate to provide a View for each row. An alternative method would be to use one of the built in layouts defined in Android.Resources.Layout. The Xamarin docs Populating a ListView with Data provide examples of how to do this, the example code below demonstrates this:-

The ObservableAdapter<T> is defined in the Helpers folder of the Galasoft.MvvmLight.Platform (Android) project. It derives from BaseAdapter<T> and uses INotifyCollectionChanged to listen to changes in the ObservableCollection.

Mark's blog post has a section titled 'Be aware of the Activity Lifecycle'. This is worth reading as he outlines how Android will destroy and re-create the Activity for example when the orientation changes and the implications of a potential memory leak. I have implemented his suggested Initialisation in the TaskListViewModel.

The Toolbar used requires a little setup to use the Material Design theme, requiring the creation of a style.

The Example Step by Step

The android example app extends the previous skeleton android app and is built alongside the existing iOS project.

Now we will remove the default Button from the Layout. Open the Main.xml in the Resources\layout folder.

Select the Button and delete it.

Select a ListView in the Toolbox and drag it onto the page.

Edit the Id of the the ListView in the PropertiesPad to ‘@+id/tasksListView’.

The Document Outline pad should now display the ListView contained in the LinearLayout as below.

Now we will create the Layout which will be used for the View for each row of the ListView. As previously mentioned in the Key Points section we could also use a pre-defined Layout from the Android.Resources.Layout. Create the TaskTemplate.axml in the layout folder - right click the layout folder and select the Add File option.

Select Android and the Layout option and name it TaskTemplate.axml.

Double click on the new file TaskTemplate.axml to open the layout. The designer will display the layout, clicking on the DocumentOutline pad will show that this is an empty LinearLayout.

Clicking the Source view will show the markup.

Return to the Designer view and use the Properties Pad to assign the Id field to ‘@+id/TaskTemplateRoot’. We will use this later to retrieve the layout in code.

Now we need to add text fields for the Task Name and Notes fields.

In the Toolbox type ‘text’ in the search and observe that there are four options for TextViews.

Select the Text (Large) widget and drag it over the layout in the designer, the background will highlight in green as you drag over. Now drop the TextView and the designer should show the TextView with ‘Large Text’.

Now edit the Id in the Properties pad to ‘@+id/NameTextView’.

Next add a TextView for the Notes field, this can be a smaller font size so select a Text (Medium) widget in the Toolbox and drag and drop it beneath the Large Text TextView.

Now edit the Id in the Properties pad to ‘@+id/NotesTextView’.

Now edit the Text properties of both the TextViews so that they are empty.

Next we will add properties to the MainActivity to get the ListView and ViewModel. Edit the MainActivity.cs to add the properties for the ViewModel and ListView:-

Now create the method which will be called by the ObservableAdapter to provide the View for each row. This will be passed into the extension method GetAdapter. Add the GetTaskAdapter method which references the TaskTemplate.axml

Now we can use the extension method GetAdapter to create the ObservableAdapter and bind the ListView to the view model's ObservableCollection. Edit the OnCreate method to create the Adpater from the ObservableCollection :-

<resources>
<style name="AppTheme"
parent="@android:style/Theme.Material.Light.DarkActionBar">
<item name="android:windowNoTitle">true</item>
<!--We will be using the toolbar so no need to show ActionBar-->
<item name="android:windowActionBar">false</item>
<!-- Set theme colours from
http://www.google.com/design/spec/style/color.html#color-color-palette-->
<!-- colorPrimary is used for the default action bar background -->
<item name="android:colorPrimary">#2196F3</item>
<!-- colorPrimaryDark is used for the status bar -->
<item name="android:colorPrimaryDark">#1976D2</item>
<!-- colorAccent is used as the default value for colorControlActivated which is used to tint widgets -->
<item name="android:colorAccent">#FF4081</item>
<!-- You can also set colorControlNormal, colorControlActivated colorControlHighlight and colorSwitchThumbNormal. -->
</style>
</resources>

Now we need to tell Android to use the correct Theme. Open the MainActivity and add ’Theme = "@style/AppTheme”’ to the existing Activity attribute ‘Theme = "@style/AppTheme", ‘

Now we can add the Toolbar. Open the Main.xml in the Designer, type ‘tool’ in the Search and drag the Toolbar to the top of the Layout.

Change the Id of the ToolBar in the Properties Pad from ‘@+id/toolbar1’ to ‘@+id/tasksToolbar’

Edit the OnCreate method of the MainActivity to add:-

var toolbar = FindViewById<Toolbar>(
Resource.Id.tasksToolbar);
//Toolbar will now take on default Action Bar characteristics
SetActionBar (toolbar);
//You can now use and reference the ActionBar
ActionBar.Title = "Hello from Toolbar";

Run the application and we now have a functioning button in the Toolbar to add tasks. Pressing the Button will create a new Task with the name ‘New Task’.

When running the Android and iOS applications side by side as shown below the Android version could do with a little more work on the styling, the iOS defaults to something more presentable straight away.

To improve the styling of the Toolbar open the Main.axml and edit the source. Setting the Background and Title of the Toolbar, aligning the Add Button to the right and increasing it's font size help:-

Now we have two (admittedly basic) apps which share the same ViewModel and Model using the MVVMLight framework. There hasn't been that much of a learning curve if you already have experience of using the MVVM pattern with MVVMLight or Prism on say WPF or Windows Runtime then much of that knowledge is transferable.