Second look at Xamarin.Forms: building OData client

A few weeks ago I wrote a blog post about getting started with Xamarin.Forms. While I went through the full cycle of creating Xamarin.Forms applications on all three supported mobile platforms, the actual application (“Hello, Forms” greeting) was too dull to give an impression about the product UI capabilities.

After that I continued working on my pet project – a cross-platform OData client library Simple.OData.Client. In addition to a NuGet PCL package I also wanted to publish the library in Xamarin Component Store, and Xamarin Store submissions require samples for all supported platforms. Earlier I planned to write three separate samples, but with the release of Xamarin.Forms there is a much easier way to write small prototype-alike apps for such purposes. I asked folks at Xamarin whether it would be acceptable to submit component samples written using Xamarin.Forms, and it turned out that it would be the first such submission but it would be OK and in fact worth gathering some experience.

Prototyping NuGetFinder

The sample that I planned to write had to demonstrate capabilities of an OData library, and NuGet is definitely the most popular OData feed among developers. I decided to write a simple NuGet package finder with three pages: a page to specify package search criteria, a result page with a list of matching packages and a page with package details. I quickly made a UI prototype using Balsamiq Mockups.

Mockups

Choosing between Portable and Shared projects

As I wrote in my “First look” post, Xamarin Visual Studio add-on and Xamarin Studio install mobile apps templates that give developers a choice between applications based on Shared (Universal) projects and Portable projects. The first option is about sharing only projects assets, not resulting binaries. The second option is based on portable class libraries (PCL).

I am a big fan of portable class libraries, and Simple.OData.Client itself is a PCL, but after some considerations I decided to build Xamarin Store samples based on Shared projects. The main reason for this is that even though I wanted samples to reuse common code, I also wanted them to be autonomous, so a sample project assembly would contain its user interface rather that referencing another PCL.

C# or XAML?

Xamarin.Forms support describing user interface either using markup language (its own XAML dialect) or directly in C#. Both methods give same results, but for the time being none of them has comprehensive documentation, and with C# you are guarded by a compiler and guided by Intellisense. Writing XAML you must know markup and watch typos. I concluded that at this point it will be easier to describe UI elements in C#, but I plan to use XAML in the future when it’s better documented.

Where are those radio buttons?

I created a solution with shared UI assets and applications for iOS, Android and Windows Phone and started implementing its UI based on my mockups. I am a backend developer during daytime, so I have good excuses for not knowing much about available UI mobile controls. And it took me some time to realize that there is not such a thing as cross-platform radio button control. Xamarin doesn’t want to repeat a mistake made by designers of Java applets and offer cross-platform user interface elements that would look equally bad on each platform. Instead they offer UI abstractions that can translate into native controls. And since Xamarin.Forms is a multiplatform product, its UI elements are limited with those that can be found on all three platforms. Thus no radio or check buttons. I ended up with Picker control that provides the same functionality (although with a very different look).

Search page

Search page is the page that sets up and performs communication with the NuGet OData feed. The user enters search details and clicks “Search” button triggering the following code:

searchButton.Clicked += async (sender, e) =>
{
    var packages = await FindPackagesAsync();
    var resultsPage = new ResultsPage(packages);
    await this.Navigation.PushAsync(resultsPage);
};

And here’s the definition of FindPackagesAsync:

private async Task<IEnumerable<Package>> FindPackagesAsync()
{
    int count = 0;
    switch (_resultSizePicker.SelectedIndex)
    {
        case 0: count = 10; break;
        case 1: count = 25; break;
        case 2: count = 100; break;
    }

    var odataClient = new ODataClient("https://nuget.org/api/v1");
    var command = odataClient
        .For<Package>("Packages")
        .OrderByDescending(x => x.DownloadCount)
        .Top(count);

    switch (_sortPicker.SelectedIndex)
    {
        case 0:
            command.OrderByDescending(x => x.DownloadCount);
            break;
        case 1:
            command.OrderBy(x => x.Id);
            break;
        case 2:
            command.OrderByDescending(x => x.LastUpdated);
            break;
    }

    if (!string.IsNullOrEmpty(_searchText.Text))
    {
        command.Filter(x => x.Title.Contains(_searchText.Text) && x.IsLatestVersion);
    }
    else
    {
        command.Filter(x => x.IsLatestVersion);
    }

    command.Select(x => new {
        x.Id, x.Title, x.Version, x.LastUpdated, x.DownloadCount, 
        x.VersionDownloadCount, x.PackageSize, x.Authors, x.Dependencies });

    return await command.FindEntriesAsync();
}

Here how the Search page looks on iPhone simulator:

SearchPage

Nothing fancy, but enough to prototype page UI on all major mobile platforms.

Results page

Results page is essentially a list of packages satisfying search criteria with an event handler for a selected item:

resultList.ItemSelected += (sender, e) =>
{
    var package = (PackageViewModel)e.SelectedItem;
    var detailsPage = new DetailsPage();
    detailsPage.BindingContext = package;
    Navigation.PushAsync(detailsPage);
};

Here’s how the results pages look on an Android simulator:

ResultsPage

Details page

Selected package details are shown on a new page that consists of label and text box controls. The programming logic is very simple, here’s a code extract that assigns package title and package id:

var titleLabel = new Label() { Font = Font.SystemFontOfSize(NamedSize.Large) };
titleLabel.SetBinding(Label.TextProperty, "Title");
stackLayout.Children.Add(titleLabel);
var idLayout = new StackLayout() { Orientation = StackOrientation.Horizontal };
idLayout.Children.Add(new Label() { Text = "Package Id: " });
var idLabel = new Label();
idLabel.SetBinding(Label.TextProperty, "Id");
idLayout.Children.Add(idLabel);
stackLayout.Children.Add(idLayout);

Here’s how Details page look on Windows Phone emulator:

DetailsPage

And now there is a new Xamarin component!

These samples have been packaged and submitted together with Simple.OData.Client library. They are now available in Xamarin Component Store. And the sample source code is also available from the GitHub repository.

Component

Advertisements