UWP Basics

  • 10/11/2018

In this sample chapter from Programming for Mixed Reality with Windows 10, Unity, Vuforia, and UrhoSharp, dive into the basics of a Universal Windows Platform (UWP) app and learn how it runs across various Windows 10 devices.

In this chapter, you will discover the exact structure of the UWP app. You will learn the execution flow, from the entry point up to displaying the view. You will also see how views are implemented, explore common programming approaches for improving code maintainability and testability, study data binding, and examine the Model–View–ViewModel (MVVM) software architectural pattern. Finally, you’ll see how UWP apps can run across various Windows 10 devices and how to use intrinsic UWP programming interfaces to adjust the app’s view and logic for various platforms. These concepts will be used throughout this part of the book.

XAML and UI

The HelloWorld app we developed in Chapter 3 has three main elements:

  • The auto-generated Program class with the Main method, representing the entry point of every C# app

  • The App class, which handles all the logic related to the app lifecycle and app services

  • MainPage, which implements a default view

To better understand the app execution model, let’s briefly analyze the UWP app lifecycle. Figure 4-1 presents a simple flowchart of this lifecycle and associated events. Initially, the app is not running. It leaves this idle state after being launched by the user (in which case the OnLaunched event of the App class is raised) or activated by the operating system (in which case the OnActivated event is raised). After the app is launched or activated, it enters the running in background state, in which the UI is still invisible. From here on, the app can periodically switch between the running in background, running in foreground (in which case the UI is visible), and suspended states.

FIGURE 4-1

FIGURE 4-1 The UWP app lifecycle.

As shown in Figure 4-1, Windows 10 can suspend the app to save resources. When the transition between each lifecycle state occurs, one of the following corresponding events is raised:

  • LeavingBackground This is fired when the app transitions from the running in background state to the running in foreground state.

  • EnteredBackground This is raised when the app transitions from the running foreground state to the running in background state.

  • Suspending This is fired when the app is suspended—that is, transitioned from the running in background state to the suspended state.

  • Resuming This occurs when the app transitions from the suspended state to the running in background state.

Before Windows 10, version 1607 (Anniversary Edition), the app lifecycle did not include the running in background and running in foreground states. Therefore, the app could periodically transition between running and suspended states.

Let’s now see where the lifecycle fits in. Listing 4-1 shows the automatically generated Program class. This class is created whenever you compile your UWP app. You can find the resulting code in the App.g.i.cs file under the obj folder. As Listing 4-1 shows, the Program.Main method has only one statement, which is responsible for initializing the App class. From this point, the control flow is directed to that class.

LISTING 4-1 The automatically generated Program class

public static class Program
{
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(
        "Microsoft.Windows.UI.Xaml.Build.Tasks"," 14.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    static void Main(string[] args)
    {
        global::Windows.UI.Xaml.Application.Start((p) => new App());
    }
}

Listing 4-2 shows a constructor of the App class. This constructor invokes the InitializeComponent method. This method is also automatically generated in the App.g.i.cs file. The constructor then registers the OnSuspending method to handle the App.Suspending event. You use this event to save the app state. If the code responsible for saving an app state is asynchronous, an event handler can complete before you save data. Hence, to delay its execution, you use an instance of SuspendingDeferral. Listing 4-2 shows how to get such an instance with the GetDeferral method of the SuspendingEventArgs.SuspendingOperation class instance. When the asynchronous code has finished, you invoke the Complete method of the SuspendingDeferral class instance to inform the system that it can safely suspend your app. Starting with the Anniversary Edition of Windows 10, it is recommended that you use the EnteredBackground event to save the app state. You can wire to this event as shown in Listing 4-3.

LISTING 4-2 A fragment of the App class

public App()
{
    InitializeComponent();
    Suspending += OnSuspending;
}

private void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();
    deferral.Complete();
}

LISTING 4-3 Wiring to the EnteredBackground event

public App()
{
    InitializeComponent();
    Suspending += OnSuspending;

    EnteredBackground += App_EnteredBackground;
}

private void App_EnteredBackground(object sender, EnteredBackgroundEventArgs e)
{
    // Starting from Windows 10 Anniversary Edition, it is recommended 
    // to use this event to store app state 
}

As shown in Figure 4-1, the App class uses several other events during the app lifecycle. One is the OnLaunched event, invoked when the user executes the app. A default implementation of this method appears in Listing 4-4. Briefly, this method creates a Frame object, which displays application views and handles navigation between them. Subsequently, depending on the previous activation (the PreviousExecutionState property of the event arguments), OnLaunched checks whether the app state and/or last view should be restored. Typically, when you run the app for the first time and it is not activated from the background, the OnLaunched event will reach the following statement:

rootFrame.Navigate(typeof(MainPage), e.Arguments);

This creates and displays a view, declared in the MainPage class. From this point, the control flow is redirected to that view.

LISTING 4-4 A default implementation of the OnLaunched event handler

protected override void OnLaunched(LaunchActivatedEventArgs e)
{ 
    Frame rootFrame = Window.Current.Content as Frame;

    if (rootFrame == null)
    {
        rootFrame = new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // TODO: Load state from previously suspended application
        }

        Window.Current.Content = rootFrame;
    }

    if (e.PrelaunchActivated == false)
    {
        if (rootFrame.Content == null)
        {
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        Window.Current.Activate();
    }
}

void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
    throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}

Views in the UWP apps, including the MainPage view, are composed of two distinct parts:

  • XAML declarations These are contained in the *.xaml file and declare a visual layer of the view.

  • Code-behind This is stored in the *.xaml.cs file, which implements the logic associated with a view.

The code-behind contains source code that handles events fired by the user after he or she uses any control on the visual layer. In the simplest case, this logic uses values entered by the user and updates the app state accordingly. To simplify this process and to create a clean separation between the presentation, logic, and data layers, you use data binding and the MVVM software architectural pattern.

Related resources

There are currently no related titles.