2 Comments

3856456237_f05ebd2602_o

The Portable Class Library (PCL) allows developers to share C#, F# and VB code across multiple devices, platforms and runtime environments such as .Net, Xamarin or Windows Store Apps. In this previous post you can see how you can write portable business logic and integrate it with all the various platforms. But what if you actually want to use something the other way round say the GPS position, file system etc.. What then? This is exactly his post we will look at the following topics:

  • Using Interface Segregation and Dependency Inversion to our favor
    • Interface in the PCL
    • Implementation on the Platform
  • Injecting the implementation at runtime into the PCL
  • Making the resolution of dependencies a breeze with MVVM Light

So lets get to it!

Using Dependency Injection to our favor

Remember SOLID? Well it turns out the last letter stand exactly for the pattern we will be using to solve our “How will I be able to use a platform specific feature cross platform “. The PCL code is platform independent and therefore can be used across multiple platforms, so we want to put near to all of our business logic into a PCL. Further by accessing concrete class implementations via interfaces we can define an Interface in the PCL and create it’s concrete implementation in a platform specific project.

PCLDIOverview

Dependency Injection in action

For example lets say we want to display the current OS version for each platform, this is a very platform specific feature. To access such a information in the PLC we first define an Interface in the PCL that describes the contract the implementation has to implement:

public interface ISystemInformationHandler
{
    string OSVersion { get; }
}

In the concrete platforms we can then inherit the interface and implement the handler which calls the platform specific API (bellow you see the Android implementation):

internal class SystemInformationHandler:ISystemInformationHandler
{
    #region Implementation of ISystemInformationHandler

    //public string OSVersion => System.Environment.OSVersion.ToString();
    public string OSVersion => $"Android {Android.OS.Build.VERSION.SdkInt} {Android.OS.Build.VERSION.Release}";

    #endregion
}

Now in the PCL we can have a class for example a view model that requires the handler to display the information.

public class MainViewModel : ViewModelBase
{
    private readonly ISystemInformationHandler _systemInformationHandler;

    public MainViewModel(ISystemInformationHandler systemInformationHandler)
    {
        if (systemInformationHandler == null) throw new ArgumentNullException(nameof(systemInformationHandler));
        _systemInformationHandler = systemInformationHandler;
    }

    public string OSVersion => _systemInformationHandler.OSVersion;
}

The view model requires as a parameter argument an instance of the IOSVersionHandler interface. So when we create an instance of the MainViewModel in the platform project, we can simply create an instance of interface and pass it into the view model when we create it.

var mainViewModel = new MainViewModel(new SystemInformationHandler());

And receive the following output for e.g. Android:

 

Cross platform Dependency resolution with MVVM Lights

Now resolving all of these dependencies by hand can get very tedious over time. You might have noticed that I’m using MVVM Light which comes with a lightweight Dependency Injection Container called Simple IoC. Lets see how we can use this component to further streamline our cross platform development efforts.

Note:for an introduction to MVVM Light please refer to this blog post for AndroidoriOSto get you started with the basics.

In the PCL we have the ViewModelLocator.cs which defines all of the instances used, but without the platform specific resolution.

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

        if (ViewModelBase.IsInDesignModeStatic)
        {
            // Create design time view services and models
            SimpleIoc.Default.Register<ISystemInformationHandler, SystemInformationHandlerStub>();
        }

        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }
}

On each platform we now extend the Locator and register the platform specific classes i.e. resolution for interfaces.

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

    private Locator()
    {
        SimpleIoc.Default.Register<ISystemInformationHandler, SystemInformationHandler>();
    }
}

Now we can simply request an instance of the view model (MVVM Light per default only creates one instance for each registered class) and use it. In Android this would look something like this in the MainActivity.cs:

[Activity(Label = "PclDISample.Droid", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    #region UI Controls

    private TextView OSVersion => FindViewById<TextView>(Resource.Id.OSVersion);

    #endregion

    private MainViewModel VM => Locator.Instance.Main;

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

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

        // Get our button from the layout resource,
        // and attach an event to it
        OSVersion.Text = VM.OSVersion;

        var mainViewModel = new MainViewModel(new SystemInformationHandler());
    }
}

In Windows 10 we can simply set the Datacontext accordingly in XAML:

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

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="{Binding OSVersion}" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TitleTextBlockStyle}"></TextBlock>
    </Grid>
</Page>

As you can see once all is registered with the simple Inversion of Control Container (IoC) of MVVM Light all of the dependency resolution will be performed automatically. If a dependency is missing, an exception will be thrown at runtime (not during compilation), so make sure to test all your views, user controls et al that they load correctly.

Conclusion

In this post you saw how you can use Dependency Injection to provide platform specific features to cross platform code located in the PCL without creating any circular dependency errors. By using interfaces in the PCL and injecting the concrete implementations during runtime we can create thin wrappers that provide platform specific features through a generic defined interface. Finally we saw how we can use MVVM Light to create a more manageable and more manageable dependency resolution with the Simple IoC Locator.

You can find the complete sample on GitHub.

Big thanks to Laurent Bugnion the creator the MVVM Light.

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.

1 Comments

For my recent blog post about how to consume a web service in the Portable Class Library (PCL) I decided to write the client for Windows 10 which allows to create apps for every platform that runs Windows 10. In this post I will focus on the platforms Desktop, Tablet and Mobile showing how to create a basic application based on a MVVM architecture. To create a Windows 10 app you will need a computer running Windows 10 and Visual Studio 2015.

Creating a basic app

First lets create a list of people that we can navigate to in the detail view. Here fore we will create two pages. On the first page MainPage.xaml we will simply show the list:

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

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <GridView ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"></GridView>

        <AppBar VerticalAlignment="Bottom" IsOpen="True" >
            <AppBarButton Icon="Add" Label="Add Person" Command="{Binding AddNewPerson}" />
        </AppBar>
    </Grid>
</Page>

The user can select an element of the list on which we will navigate to the detail of the person allowing us to edit the person. This is done in the MainViewModel.cs which is based on the MVVM Light Framework for implementation:

public class MainViewModel:ViewModelBase
{
    private readonly IPersonService _personService;
    private ObservableCollection<Person> _people;
    private Person _selectedPerson;

    public MainViewModel(IPersonService personService)
    {
        if (personService == null) throw new ArgumentNullException(nameof(personService));
        _personService = personService;
        _people = new ObservableCollection<Person>();
        ShowPerson = person => { };
        AddNewPerson = new RelayCommand(() => ShowPerson(-1));
    }

    public ObservableCollection<Person> People => _people;
    public Action<int> ShowPerson { get; set; }

    public Person SelectedPerson
    {
        get { return _selectedPerson; }
        set
        {
            if (_selectedPerson == value) return;
            _selectedPerson = value;
            RaisePropertyChanged(nameof(SelectedPerson));
            if (_selectedPerson != null) ShowPerson(_people.IndexOf(_selectedPerson));
        }
    }

    public ICommand AddNewPerson { get; private set; }

    public async Task Init()
    {
        var people = await _personService.GetPeople();

        _people.Clear();

        foreach (var person in people)
        {
            _people.Add(person);
        }
    }
}

The View Model also prepares the List of people that is displayed on the main page. The PersonDetailPage.xaml will allow to edit the first and surname of the person:

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

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBox Header="Firstname" Text="{Binding Firstname, Mode=TwoWay}"/>
        <TextBox Header="Lastname" Text="{Binding Lastname, Mode=TwoWay}"/>
        <Button Content="Save" Command="{Binding StoreCommand, Mode=TwoWay}" IsEnabled="{Binding HasPendingChanges}" HorizontalAlignment="Center" Margin="0,10"/>
    </StackPanel>
</Page>

When selecting save the person will be updated, all the logic is implemented in the PersonDetailViewModel.cs:

public class PersonDetailViewModel:ViewModelBase
{
    private readonly IPersonService _personService;
    private int _id;
    private string _firstname;
    private string _lastname;
    private bool _hasPendingChanges;

    public PersonDetailViewModel(IPersonService personService)
    {
        if (personService == null) throw new ArgumentNullException(nameof(personService));
        _personService = personService;

        StoreCommand = new RelayCommand(StorePerson, () => true);
        HasPendingChanges = false;
    }

    public bool HasPendingChanges
    {
        get { return _hasPendingChanges; }
        set
        {
            if (value == _hasPendingChanges) return;
            _hasPendingChanges = value;
            RaisePropertyChanged(nameof(HasPendingChanges));
        }
    }

    public string Firstname
    {
        get { return _firstname; }
        set
        {
            if (value == _firstname) return;
            _firstname = value;
            HasPendingChanges = true;
            RaisePropertyChanged(nameof(Firstname));
        }
    }

    public string Lastname
    {
        get { return _lastname; }
        set
        {
            if (_lastname == value) return;
            _lastname = value;
            HasPendingChanges = true;
            RaisePropertyChanged(nameof(Lastname));
        }
    }

    public ICommand StoreCommand { get; set; }

    public async Task Init(int id)
    {
        _id = id;
        var person = id > 0 ? (await _personService.GetPeople()).ToList()[id] : new Person("", "");
        Firstname = person.FirstName;
        Lastname = person.LastName;
        HasPendingChanges = false;
    }

    private async void StorePerson()
    {
        HasPendingChanges = false;

        var person = new Person(Firstname, Lastname);

        if (_id >= 0)
        {
            await _personService.UpdatePerson(_id, person);
        }
        else
        {
            await _personService.CreatePerson(person);
        }
    }
}

To prevent the user from invoking the storing of a person multiple times the store button is only enabled when there are pending changes and you probably want to improve the error handling in production code as it is non-existent in the StorePerson method.

Basic Navigation

From the main page we implement the navigation in MainPage.xaml.cs which allows the user to navigate to the detail page. We also pass along a navigation parameter which contains the ID or ahem in this basic example the array index of the person we want to see:

private void ShowPerson(int personId)
{
    Frame.Navigate(typeof (PersonDetailPage), personId);
    _viewModel.SelectedPerson = null;
}

The navigation is done over Frame.Navigate, which takes the type of the target and a parameter as an argument. The SelectedPerson is then set to null, after invoking the navigation. This is done so that the user may reselect the person the second time around.

Additionally when the user adds a person over the AppBar it will invoke the same navigation method but pass in the –1 as parameter indicating that no Index is set.

Further the user has the possibility to navigate back to the main page. Here fore we have to enable the back navigation which we set in the Loaded event handler of the person detail page and add an event handler for the BackRequest:

private void PersonDetail_OnLoaded(object sender, RoutedEventArgs e)
{
    SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
}

The event handler is implemented as follows:

private void OnBackRequested(object sender, BackRequestedEventArgs backRequestedEventArgs)
{
    if (Frame.CanGoBack)
    {
        Frame.GoBack();
        backRequestedEventArgs.Handled = true;
    }
}

While testing the app under Windows 10 mobile I noticed that the navigation was invoked twice when selecting the hardware back button. By setting the Handled property to true in the event arguments the framework is indicated that the navigation has been taken care of.

Taking it to other form factors

A great thing about creating your apps as a Universal Windows Platform app is that the APIs remain the same across the devices. In regards to the upcoming Windows 10 Mobile release we can even reuse the UI code. So we can run this basic app on a phone without making any changes. The UI will be automatically adopted to the new form factor.

Now of course for more complex apps you will want to use different layouts according to the screen size, but even then you will be creating adaptive layouts (same as with responsive Websites) rather than developing multiple apps to target different platforms. So a lot less overhead and work to have a running app across multiple form factors.

Conclusion

In this post we saw how to create a basic Windows 10 UWP app including basic navigation features and how to implement the MVVM pattern. If you are coming from a WPF, Silverlight, Windows 8.x or Windows Phone background you have seen that a lot of elements are very familiar.

I’ve been lately playing around with F# which unfortunately is currently not a supported language to write UWP apps. This also includes not being able to share Portable Class Libraries with UWP apps. If you feel the same way as me or want to throw the F# community a bone please let Microsoft know that they enable support for F# UWP apps here.

You can find the entire sample code of this blog post on GitHub.