Windows 10 UWP

Windows 10 UWP and Caliburn Micro

Lets walk through the setup of a blank UWP (Universal Windows Platform) project with Caliburn Micro – an MVVM framework. I’m going to cover the minimal steps you in order to get up and running. I’m assuming a basic knowledge of MVVM and CM.

If you prefer a pre-existing template to work with, check out this post by Bogdan Bujdea explaining the template he wrote. What we will produce will be very similar but simpler.

We will be using the WinRT” functionality in Caliburn.Micro. The WinRT tag threw me off when I was searching for information. That being said, what we’re doing is near identical to what you would need to do in Windows 8/8.1. See this series by Terry Marshall, which explains everything in more detail than I will.

PREREQUISITES

  • PC running Windows 10 PC
  • Visual Studio 2015 (community edition is fine)
  • Windows 10 SDK
  • Developer mode enabled in Settings > Update & Security > For developers

See this article for more information.

Getting Started

Open Visual Studio 2015. Select New Project… and then Visual C# > Windows > Universal > Blank App (Universal Windows). You have the option to “Show Telemetry in the Windows 10 dev centre” and “Enable richer analytics with Application Insights”. You’re welcome to select one/both.

UWP Caliburn - New Project
Select a blank project

Add the caliburn.micro nuget package

Open the NuGet Package Manager (i.e. right-click the project and select Manage NuGet Packages). Search for Caliburn.Micro and install it. If you prefer the command line, enter this into the package manager console
install-package Caliburn.Micro

UWP Caliburn - Find package
Add the caliburn.micro nuget package

Folders

Create a folder in the root of your project called Views and another called ViewModels.

Within the ViewModels folder, we need a class called ViewModelBase. This inherits from Screen. Going forward, your view models will inherit from ViewModelBase.

using Caliburn.Micro;

namespace UWPCaliburnMicro.ViewModels
{
    public class ViewModelBase : Screen
    {
        protected readonly INavigationService PageNavigationService;

        protected ViewModelBase(INavigationService pageNavigationService)
        {
            PageNavigationService = pageNavigationService;
        }

        public bool CanGoBack
        {
            get { return PageNavigationService.CanGoBack; }
        }

        protected void NavigateTo<T>()
        {
            PageNavigationService.Navigate<T>();
        }

        public void GoBack()
        {
            PageNavigationService.GoBack();
        }
    }
}

In this example, I’m going to have a single view called Hello. As such, I need to create a blank XAML page under the Views folder called HelloView.xaml and a class in ViewModels called HelloViewModel.cs. We’re following the Caliburn.Micro naming convention.

Create a view and viewmodel

In my example, I am going to create a very simple view called HelloWorld, which will be my main page. It consists purely of a textbox and button. Note that I didn’t touch the code behind on the view and deleted MainPage.xaml.

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

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Orientation="Vertical" Margin="20">
            <TextBox x:Name="MyMessage" />
            <Button x:Name="SayHello" Content="Say hello" Margin="0,10" />
        </StackPanel>
    </Grid>
</Page>

Here’s the ViewModel code. Simple stuff – if you press the button, I populate the textbox.

using Caliburn.Micro;

namespace UWPCaliburnMicro.ViewModels
{
    public class HelloWorldViewModel : ViewModelBase
    {
        private INavigationService _pageNavigationService;

        public HelloWorldViewModel(INavigationService pageNavigationService) : base(pageNavigationService)
        {
            _pageNavigationService = pageNavigationService;
        }

        private string _myMessage;
        public string MyMessage
        {
            get { return _myMessage; }
            set
            {
                _myMessage = value;
                NotifyOfPropertyChange(() => MyMessage);
            }
        }

        public void SayHello()
        {
            MyMessage = "Hello World!";
        }
    }
}

App.xaml

We need to make bit a fair of changes here. Let’s start in App.xaml. It’s currently based on Application. We need to change that to CaliburnApplication. If you’re new to XAML, what we’ve done is add the line xmlns:cm=”using:Caliburn.Micro” (I’m defining an XML namespace to Caliburn.Micro) and then using “cm”, which I defined, to reference the CaliburnApplication.

<cm:CaliburnApplication x:Class="UWPCaliburnMicro.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:UWPCaliburnMicro" xmlns:cm="using:Caliburn.Micro" RequestedTheme="Light">

</cm:CaliburnApplication>

App.xaml.cs

Nothing too serious here. A few things to note:

  • In my example I’ve still got the telemetry client (Application Insights)
  • I’m generally trying to keep it similar to the blank template in that we’re supporting OnLaunching, OnResuming, OnSuspending. This is important as they are all events you should be handling
  • We overwrite several functions from CaliburnApplication including Configure (where we setup our container and add all our view models) as well as GetAllInstances, BuildUp, GetInstance

In writing a UWP, make sure you build the appropriate functionality in OnResuming and OnSuspending.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml.Controls;
using Caliburn.Micro;
using Microsoft.ApplicationInsights;
using UWPCaliburnMicro.ViewModels;
using UWPCaliburnMicro.Views;

namespace UWPCaliburnMicro
{
    ///
<summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>

    sealed partial class App
    {
        private WinRTContainer _container;

        ///
<summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>

        public App()
        {
            WindowsAppInitializer.InitializeAsync();
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        protected override void Configure()
        {
            _container = new WinRTContainer();

            _container.RegisterWinRTServices();

            // Make sure to register your containers here
            _container.PerRequest<HelloWorldViewModel>();
        }

        ///
<summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>

        /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif
            // I am launching my main view here
            DisplayRootView<HelloWorldView>();
        }

        ///
<summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>

        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        protected override void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }

        protected override void PrepareViewFirst(Frame rootFrame)
        {
            _container.RegisterNavigationService(rootFrame);
        }

        protected override object GetInstance(Type service, string key)
        {
            return _container.GetInstance(service, key);
        }

        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return _container.GetAllInstances(service);
        }

        protected override void BuildUp(object instance)
        {
            _container.BuildUp(instance);
        }

    }
}

Behaviours sdk reference

In your project, right-click References and select Add Reference… Under Universal Windows > Extensions select Behaviours SDK (XAML)

Select Behaviours SDK (XAML)
Select Behaviours SDK (XAML)

DONE

We’ve now created a simple UWP using Caliburn Micro!

The final product. A simple Hello World application
The final product. A simple Hello World application

4 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s