DotNetCurry Logo

Hello Xamarin.Forms!

Posted by: Nish Anil , on 10/13/2014, in Category Windows Phone
Views: 24431
Abstract: Xamarin.Forms makes developing mobile applications on all three major platforms - Android, iOS and Windows Phone, a breeze. In this article, we will build a fully loaded Xamarin.Forms Vehicle Service app.

Xamarin.Forms is a simple yet powerful UI toolkit that gives an abstraction layer for creating mobile native user interfaces for iOS, Android and Windows Phone. It gives you a rich API in C# and lets you share as much code as possible across all the three platforms. Sharing code in the Xamarin platform is super easy with Portable Class Libraries or simply using the sweet Shared Projects. Until the Xamarin.Forms release, you could only share your models, business logic, data access layer and any other code that's platform independent. In fact, this is by design and is a deliberate effort to give developers the maximum advantage of using platform specific features, without compromising on sharing business logic.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free .NET tutorials from experts

Having said that, we knew, not every app needs to have a platform level customization. For e.g. for enterprises who want to build an app to fill up their backend databases - all that they need is just a few forms in their app. Building these forms three times (for iOS, Android and Windows Phone ) is definitely not a great experience. So there was a high demand for a UI abstraction layer that gives a simple API to write one piece of code and magically render respective native interfaces on every platform.

When we set out to build Xamarin.Forms we knew it was never easy because every platform differs in subtle ways. For e.g., Navigation - iPhones and iPads have just one physical button that is "Home" and all the back navigations were done by a button on the top left corner within the app. However Android and Windows had hardware level Back buttons. Even some of the controls were rendered differently on each platform for e.g. Tabs in iOS had the Tab buttons at the bottom, Android had them below the top navigation bar and Windows Phone doesn't have it at all - it's a Pivot control there.

So it took us nearly 18 months to build an API that cleanly abstracts away the platform divergence and renders appropriate platform controls. Xamarin.Forms is more than just the API. It’s also the patterns library that helps developers write much cleaner and maintainable code. You can leverage your Model-View-ViewModel skills with data binding, which we think is the most powerful feature of this release.

xamarin-code-sharing

In this article, I will take you through the steps involved in building your first fully loaded Xamarin.Forms app. You will see how you can maintain a single code base across iOS, Android and Windows Phone; leverage your XAML data binding skills, learn to customize a native control and write platform specific code (you do have it when you want it!).

I understand, in the previous issue of DNC magazine, Filip Ekberg wrote a fantastic article titled Introducing Xamarin - A REST API based HackerNews application that works on iOS, Android and Windows Phone . I highly recommend you to read that article if you haven't.

 

Building a Vehicle Service Reminder in Xamarin

I often forget when was the last time I serviced my car and when its next service is due, so I built an app that reminds me when my car is due for service. I’m going to take you through a step-by-step approach of building this app using XAML and the MVVM pattern. The code is all out there in GitHub for free. Feel free to fork and add your favorite feature!

Before we start

What we need is –

- Two Screens

  • o A form that can input Name, Registration Number, Vehicle Type(Car, bike etc), Last Service Date, Next Service Date and a Reminder Date
  • o A list that shows all the Vehicles and they due dates (Typically a Home Screen)

- SQLite Data Access layer

- Reminder Service (Differs in all platforms for e.g. UILocalNotification in iOS, Microsoft.Phone.Scheduler.Reminder in Windows Phone and AlarmManager in Android.)

reminder-screens-all

Creating a New Xamarin Project

When you install Xamarin, you get a Mobile Apps project template right inside Visual Studio. To create a new Xamarin.Forms project, File -> New -> Project -> Mobile Apps and choose Blank App (Xamarin.Forms Shared)

xamarin-blank-app

PCL vs Shared Project, What’s best?

Choosing between a Shared Project or Portable Class Library (PCL) totally depends on how you want to architect your application. Both have their own advantages and disadvantages. For e.g. Shared Projects is nothing but an arbitrary project type that has files linked to referencing projects. They can be thought of as files within the referencing app, than a project that gives you a dll or exe. You’re free to make use of conditional compiling statements that gives you flexibility in adding platform specific code within this project giving you space to share more code. Yes! Sometimes your code will look ugly and as your code grows, maintaining this could be harder.

PCL on the other hand is simply a compiled library that will be referenced on the target platform apps just like any another library. Since conditional compiling is not supported, you may have to use some patterns like Provider Pattern to better maintain the code. PCL works great if you are a third party library provider who ships updates often.

As said above, it’s totally your architectural decision to choose between the two – you know what’s best for your app.

Project Structure

Xamarin.Forms automatically creates four projects in Visual Studio –

xamarin-project-structure

  • Shared Project – Where all the shared logic resides.
  • Android Project – Android specific platform code.
  • iOS Project – iOS specific platform code.
  • Windows Phone Project – WP specific platform code.

Ideally, you don’t have to write anything inside the platform specific code, because Xamarin.Forms will wire things up for you!

Creating the User Interface in XAML

There are two approaches to create user interfaces in Xamarin.Forms. The first one is to create UI views entirely with source code using the Xamarin.Forms API. The other option available is to use Extensible Application Markup Language (XAML), which is the approach I’ve taken to build this demo.

Please remember XAML is a markup language that follows xml syntax and the controls that you will be referencing here are part of the Xamarin.Forms.Controls namespace unlike the System.Windows in WPF. Though you will find a lot of similarities in the code, they aren’t the same. For e.g. In Xamarin.Forms, You have the instead of . However they do the same thing – Layout controls in a stack.

A Page

A page is the topmost visual element that occupies the entire screen and has just a single child. You can choose from five different pages –

layouts

  • ContentPage – A single view often a container to Visual Elements
  • MasterDetailsPage – A page that manages two panes
  • NavigationPage – A page that stacks other content pages – usually used for Navigation
  • TabbedPage – A page that allows navigation using Tabs
  • CarouselPage – A page that supports swipe gestures between subpages (e.g. gallery)

Now, let’s start writing our app starting with Pages.

EditReminderPage.xaml

EditReminderPage is a ContentPage that has the XAML for creating visual elements for Name, Registration Number, Vehicle Type(Car, bike etc), Last Service Date, Next Service Date, Reminder Date and Save implementation. These controls can be placed on the screen using any of the seven layouts or Views provided by the Xamarin.Forms API.

For this page, I used a TableView that holds the rows of cells. The advantage of using TableView is that it gives you Human Interface Guidelines Compliant user interfaces and they are extremely flexible in terms of customizing each cell.

The following screenshot shows what cells are used and how they are visually rendered with the appropriate controls in iOS and Android.

edit-reminder-pagexaml

Let’s look at it one by one -

TableSection

TableSection logically groups elements on the screen. It provides an appropriate title to every group.


    
        
            
            
                
            
    


EntryCell, TextCell, ImageCell & SwitchCell

An EntryCell provides a label and a single line text entry field. In our app, this is best suited for the Vehicle Name and Registration No.



A TextCell consists of a Primary and a Secondary Text. They’re set using Text and Detail properties.


An ImageCell is simply a TextCell that includes an image.


A SwitchCell is a cell with a label and an on/off switch.


Notice the Data Binding syntax above – Yes, You guessed that right! You can leverage data bindings in Xamarin.Forms apps.

Use ViewCell to customize a cell

Cells can be customized completely by using ViewCell. ViewCell In this case is used to incorporate a DatePicker and a Label. Here’s how they look on all three platforms!

datepicker


    
        


Reusing Custom Cells (PickerCellView.xaml)

In my app, I use a Picker for choosing the Service Interval and Remind Me elements. I take a different approach here to show you how you can customize the picker to completely act on a VIewModel that is provided. I first create a ContentView in XAML and name it PickerCellView.xaml



    
        


Next, I create a PickerCell that inherits from ViewCell where T is a ViewModel that implements the IPickerCellViewModel. Finally, set the View of the PickerCell to the Picker.

public class PickerCell : ViewCell where T : IPickerCellViewModel
{

    public static readonly BindableProperty PickerCellViewModelProperty =
            BindableProperty.Create, T>(p => p.PickerCellViewModel, Activator.CreateInstance());

    public T PickerCellViewModel
    {
        get { return (T)GetValue(PickerCellViewModelProperty); }
        set { SetValue(PickerCellViewModelProperty, value); }
    }


    PickerCellView vw;
    public PickerCell()
    {
        var vw = new PickerCellView();
        vw.BindingContext = PickerCellViewModel;
        View = vw;
    }

}

A Note on BindingContext & BindableProperties

Bindings are used most often to connect the visuals of a program with an underlying data model, usually in a realization of the MVVM (Model-View-ViewModel) application architecture. A BindingContext is just like DataContext in WPF and usually set to your ViewModels. BindableProperties are just like DependencyProperties in WPF. Create them when you want the properties to be participating in Data Bindings. In this case, we are setting the ViewModel as the BindableProperty and assigning it to the BindingContext of the control so that any changes to the property are reflected in the UI and vice versa.

Finally, these custom cells are used in the TableView with appropriate ViewModels




Keep OnPlatform handy

Sometimes you have the need to write platform specific code in XAML. In my case, I wanted to set a padding of 20 in the ContentPage in iOS so as to avoid the overlapping of the status bar. Since the 20 units on top is only required in case of iOS, I can make use of OnPlatform to set that.


    
        
            0, 20, 0, 0
        
        
            0, 0, 0, 0
        
        
            0, 0, 0, 0
        
    


HomePage.xaml

It’s time to create a homepage that displays the list of created Service Reminder Items.

Use a ListView for repeating data

A ListView is an ItemView that displays a collection of data as a vertical list.

homepagexaml


    
        
            
        
    


Handling Data (ReminderItemDatabase.cs)

Xamarin.Forms apps can easily access local SQLite databases, using compiler directives with Shared Projects or using PCL. Because the Shared Project code is treated as part of each individual application project, the ReminderItemDatabase class can take advantage of compiler directives to perform platform-specific operations while sharing the remainder of the code in the class.

static string DatabasePath
{
    get
    {
        var sqliteFilename = "ServiceReminder.db3";
        #if __IOS__
        string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
        string libraryPath = Path.Combine(documentsPath, "..", "Library"); // Library folder
        var path = Path.Combine(libraryPath, sqliteFilename);
        #else
        #if __ANDROID__
        string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
        var path = Path.Combine(documentsPath, sqliteFilename);
        #else
        // WinPhone
        var path = Path.Combine(ApplicationData.Current.LocalFolder.Path, sqliteFilename);;
        #endif
        #endif
        return path;
    }
}

Model (ReminderItem.cs)

model

Add some helper methods to save and retrieve our models.

static object locker = new object();

    static SQLiteConnection database = new SQLiteConnection(databasePath: DatabasePath);

    public ReminderItemDatabase()
    {
        // create the tables
        database.CreateTable();
    }

    public IEnumerable GetItems()
    {
        lock (locker)
        {
            return (from i in database.Table() select i).ToList();
        }
    }

    public ReminderItem GetItem(int id)
    {
        lock (locker)
        {
            return database.Table().FirstOrDefault(x => x.Id == id);
        }
    }

    public int SaveItem(ReminderItem item)
    {
        lock (locker)
        {
            if (item.Id != 0)
            {
                database.Update(item);
                return item.Id;
            }
            else
            {
                return database.Insert(item);
            }
        }
    }

    public int DeleteItem(int id)
    {
        lock (locker)
        {
            return database.Delete(id);
        }
    }     

SQLite.cs

To use SQLite with a Xamarin.Forms Shared Project, simply add the SQLite.Net ORM source to the project. (http://goo.gl/VYmG7q )

Please note: By default, Windows Phone does not include the SQLite database engine, so you need to ship it with your application. Download the Pre-compiled binaries for Windows Phone 8 from here http://www.sqlite.org/download.html#wp8 and install them.

Add a Reminder (Platform specific code)

Until now, whatever code I wrote is in the Shared Project and the appropriate native interfaces were rendered on all three platforms – iOS, Android and Windows Phone. Now let me show you how to write some platform specific code.

The Service Reminder app is incomplete without adding a reminder service – i.e. when the user saves the ReminderItem, the app should remind the users at the set date and time. The easiest way to implement this is by using the platform specific Reminder Services. In iOS we can use UILocalNotification, in Android it’s the Alarm Manager and in Windows Phone it’s the Microsoft.Phone.Scheduler.Reminder.

Xamarin.Forms includes a DependencyService to let shared code easily resolve Interfaces to platform-specific implementations, allowing you to access features of the iOS, Android and Windows Phone SDKs from your Shared Project.

There are three parts to a DependencyService implementation:

  • Interface - An Interface in the shared code that defines the functionality
  • Registration - An implementation of the Interface in each platform-specific application project
  • Location – Call DependencyService.Get<> in shared code to get a platform-specific instance of the Interface at run time, thereby allowing the shared code to access the underlying platform.

Interface (IReminderService.cs)

public interface IReminderService
{
    void Remind(DateTime dateTime, string title, string message);
}

Registration and Platform Implementation

(iOSReminderService.cs)

This code is written in the iOS project and it requires you to specify the [assembly] attribute, which does the registration of your implementation.

[assembly: Xamarin.Forms.Dependency(typeof(iOSReminderService))]
namespace ServiceReminder.iOS.ReminderService
{
    public class iOSReminderService : IReminderService
    {
        public void Remind(DateTime dateTime, string title, string message)
        {
            var notification = new UILocalNotification();

            //---- set the fire date (the date time in which it will fire)
            notification.FireDate =dateTime;

            //---- configure the alert stuff
            notification.AlertAction = title;
            notification.AlertBody = message;

            //---- modify the badge
            notification.ApplicationIconBadgeNumber = 1;

            //---- set the sound to be the default sound
            notification.SoundName = UILocalNotification.DefaultSoundName;

            //---- schedule it
            UIApplication.SharedApplication.ScheduleLocalNotification(notification);
        }
    }
}

(WPReminderService.cs)

Just like iOS, WP implementation has to be written in the WP project.

[assembly: Xamarin.Forms.Dependency(typeof(WPReminderService))]

namespace ServiceReminder.WinPhone.ReminderService
{
    public class WPReminderService : IReminderService
    {
        public void Remind(DateTime dateTime, string title, string message)
        {

            string param1Value = title;
            string param2Value = message;
            string queryString = "";
            if (param1Value != "" && param2Value != "")
            {
                queryString = "?param1=" + param1Value + "¶m2=" + param2Value;
            }
            else if (param1Value != "" || param2Value != "")
            {
                queryString = (param1Value != null) ? "?param1=" + param1Value : "?param2=" + param2Value;
            }
            Microsoft.Phone.Scheduler.Reminder reminder = new Microsoft.Phone.Scheduler.Reminder("ServiceReminder");
            reminder.Title = title;
            reminder.Content = message;
            reminder.BeginTime = dateTime;
            reminder.ExpirationTime = dateTime.AddDays(1);
            reminder.RecurrenceType = RecurrenceInterval.None;
            reminder.NavigationUri = new Uri("/MainPage.xaml" + queryString, UriKind.Relative);
            ;

            // Register the reminder with the system.
            ScheduledActionService.Add(reminder);

        }
    }
}

Android – How about you Fork the project and implement it. Give me a shout on twitter at @nishanil and if I like your solution, I may send you a Xamarin goodie. * Hint: use Alarm Manager

Conclusion

Xamarin.Forms makes developing mobile applications on all three major platforms a breeze. It’s a nice abstraction layer packaged with a patterns library that makes it super easy for any C# developer to write their next big app on iOS, Android and Windows Phone within no time. Xamarin makes it easy, fast and fun for you! Get your hands dirty now!

Download the entire source code from our GitHub Repository at bit.ly/dncm14-xamarinforms

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on Google+
Further Reading - Articles You May Like!
Author
Nish is a C# fanatic and has been writing softwares for web, windows & mobile platforms for almost a decade now. He is Xamarin’s first Developer Evangelist for India and a Microsoft MVP in Visual C# . He is passionate about spreading C# awesomeness and Xamarin love by helping developers build 100% native mobile applications for iOS, Android, Windows Phone & Windows platforms. Follow his adventures on twitter @nishanil


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Nk54 on Friday, February 20, 2015 7:29 AM
Very nice article.

Just to add further information about PCL : they are the kind of project recommanded by the Xamarin team because Xamarin studio supports PCL project better.