-
Template10: a new template to create Universal Windows apps – The controls
In the previous post we started to know Template10, the new open source template developed by a Microsoft, with the goal to become the starting point for every Universal Windows app developer. In this post we’re going to see some cool custom controls provided by the library.
#
The PageHeader control
One of the new features available in Windows 10, when it comes to design the user interface, is the improved flexibility regarding the application bars. In Windows and Windows Phone 8.1 you were able to place an application bar only at the bottom of the screen. Only in Windows 8.1 you were allowed to have a top application bar, but not for commanding purposes: it had to be used to make easier for the user to navigate through the sections of the application.
The bottom application bar was implemented using a control called CommandBar, which makes easier for the developer to quickly add buttons so that that the user can interact with the content on the screen. Windows 10 allows, instead, to place the CommandBar control also at the top. The PageHeader control is an extension of the CommandBar one, so that you can use it not just to provide commands to the user, but also to act as a real header of the page. Thanks to this control, it will be easier to implement the same look & feel offered by many native applications like News or Money, which offer an header with the tile of the page and a set of buttons to handle navigation or content interaction.
The first step to add a PageHeader control is to declare in the XAML page the required namespace, which is Template10.Controls, like in the following sample:
<Page x:Class="Controls.Views.MainPage" xmlns:controls="using:Template10.Controls" mc:Ignorable="d"> </Page>
Now you can add the control to your page by using the following code:
<controls:PageHeader Frame="{x:Bind Frame}" />
One of the key properties is called Frame. As we’re going to se later, one of the key features provided by the control is the built-in management of the navigation framework. To make this feature working, we need to connect to the PageHeader control the application’s frame, which handles the pages and the navigation between them: we can do it using the new x:Bind markup extensions, which is able to perform a binding with objects exposed by the code behind class.
This is how the standard PageHeader control looks like:
#
Customizing the control
The key property to customize the PageHeader control is Text, which allows to set the text that is displayed in the header (typically, the title of the page). Eventually, you can also customize the standard color that is assigned to the text and to the background, by using the HeaderForeground and HeaderBackground properties. The following samples shows a customized header, with a red text and an orange background.
<controls:PageHeader Text="Main Page" Frame="{x:Bind Frame}" HeaderBackground="Orange" HeaderForeground="Red" />
Handle navigation
The PageHeader control offers a built-in back button to handle the navigation towards the previous page of the application, which is controlled by a property called BackButtonVisibility. When this property is set to Visible, the button is displayed at the left of the header’s text.
<controls:PageHeader Text="Detail" Frame="{x:Bind Frame}" BackButtonVisibility="Visible" />
However, it’s very important to highlight that the button’s visibility isn’t controlled just by this property, but also by the operating system, which can override our configuration. Specifically:
- The control, thanks to the Frame property, is connected to the navigation’s frame. Consequently, it’s able to automatically detect if there are pages in the back stack so that if it’s empty (for example, because you’re in the main page), the button will always be hidden.
- Windows 10 can run on multiple devices, which can offer a different navigation experience. If, on the desktop, we have more freedom (we can use the virtual back button embedded in the chrome or include it in the UI of the application), on mobile instead you need to leverage the hardware back button available on every device. As such, if you set the BackButtonVisibility property of the control to Visible but the app is running on a phone, the button will be hidden anyway.
- On desktop, as we’ve seen in the previous post, we have the chance to leverage a virtual back button, which is added on the app’s chrome, to handle the navigation. If we have enabled this option (which Template10 applies by default but that can be controlled by the ShowShellBackButton property of the BootStrapper class), the PageHeader control’s button will be hidden anyway.</ol> ##
The commands
As mentioned in the beginning of the post, PageHeader extens the CommandBar control, which is used to add an application bar with one or more commands, so that the user can interact with the current content. Consequently, the PageHeader control offers the same features of the CommandBar one and follows the same principles:
- Inside the PrimaryCommands collection you can add one or more buttons, which will always be visible and represented by an icon and a label.
- Inside the SecondaryCommands collection you can add one or more buttons which, instead, will be hidden by default: the user will be able to see them only by tapping on the three dots displayed at the end of the bar. Secondary commands are represented only with a label.</ul> Inside the two collections you don’t have the freedom to add any XAML control, but there’s a specific subset of controls which has been designed to work with a CommandBar. The most used one is AppBarButton, which represents a button that the user can press. It can have an image (defined by the Icon property) and a description (defined by the Label property) and you can subscribe to the Click event to handle the user’s interaction.
The following sample code defines a PageHeader control with one primary command and two secondary commands:
<controls:PageHeader Text="Main Page" Frame="{x:Bind Frame}"> <controls:PageHeader.PrimaryCommands> <AppBarButton Icon="Forward" Label="Next" Click="OnNextClicked" /> </controls:PageHeader.PrimaryCommands> <controls:PageHeader.SecondaryCommands> <AppBarButton Label="Option 1" /> <AppBarButton Label="Option 2" /> </controls:PageHeader.SecondaryCommands> </controls:PageHeader>
- Windows 10 can run on multiple devices, which can offer a different navigation experience. If, on the desktop, we have more freedom (we can use the virtual back button embedded in the chrome or include it in the UI of the application), on mobile instead you need to leverage the hardware back button available on every device. As such, if you set the BackButtonVisibility property of the control to Visible but the app is running on a phone, the button will be hidden anyway.
</pre>
[<img title="clip_image008" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image008" src="https://i0.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image008_thumb.jpg?resize=431%2C374" width="431" height="374" data-recalc-dims="1" />](https://i2.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image008.jpg) It’s really important to evaluate how many buttons you want to add in the control, especially if you’re application targets multiple families of devices. For example, the usage of many primary commands isn’t a big deal on the desktop: since the screen is bigger and usually in landscape, there’s plenty of available space. The same rules don’t apply to a smartphone: in this scenario, it’s better to reduce the number of primary commands and rely more on the secondary ones. The following image shows the same layout with three primary commands: you can notice how it works perfectly on the desktop, but it messes up on the mobile (due to the reduced space, the buttons overlaps with the header’s text). [<img title="clip_image010" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image010" src="https://i1.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image010_thumb.jpg?resize=579%2C205" width="579" height="205" data-recalc-dims="1" />](https://i0.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image010.jpg) # # The HamburgerMenu control Another new Windows 10 feature is the **SplitView** control, which can be used to implement navigation experiences based on the hamburger menu in your applications. This approach is based on a side panel (typically, it’s placed on the left of the screen) which the user can expand by tapping a button on the top of the panel (usually, in the top left corner). Inside the panel you can usually find multiple items, which can be used to quickly jump from one section to another of the application. The name comes from the fact that the button to show or hide the panel is visually represented by thee lines, one on top of the other, which look like a hamburger between two pieces of bread. Many native applications are using this approach, like News (which uses the panel to give access to the different sections of the app) or Mail (which, instead, uses the panel to show the available mail accounts with their sub folders). The **SplitView** control is just one of the many controls that are available to define the navigation experience of your application: it’s not the only one and Microsoft doesn’t want to force you to use it in any application you create. It’s up to the developer to find the navigation approach that works best for him. Consequently, the **SplitView** control leaves a lot of freedom to the developer. It just gives you an easy way to split the page in two parts: a sliding panel and the main content. It’s up to you to define the look & feel of both parts. The downside of this freedom is that we have a bit of work to do if we want, instead, implement a traditional hamburger menu navigation, similar to the one used by some native apps. Template10 simplifies a lot our job since: 1. It offers a control called **HamburgerMenu**, which makes easier to define the panel that will contain the list of application’s sections. * It offers a way to create a **shell**, which is a special page that will act as a container for the application. The shell will contain the menu, while the content area will be filled with the various pages of the application. * It offers a set of built-in styles to recreate a panel with the same look & feel of the one used by native apps (highlight of the current section, icon support, etc.)</ol> Thanks to Template10 we’ll be able to achieve a result very close to the following one: [<img title="clip_image012" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image012" src="https://i0.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image012_thumb.png?resize=338%2C416" width="338" height="416" data-recalc-dims="1" />](https://i2.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image012.png) Let’s see how to implement it. # ## ## The HamburgerMenu control Like the **PageHeader** control, the **HamburgerMenu** one is defined inside the **Template10.Controls** namespace, which you need to add in the XAML declaration. After that, you’ll be able to add it into a page: <pre class="brush: xml;"><controls:HamburgerMenu x:Name="Menu" />
</pre>
Customization is allowed thanks to the following properties: * **HamburgerBackground** and **HamburgerForeground** define the background and foreground color of the hamburger button (the one used to show / hide the panel) * **NavButtonBackground** and **NavButtonForeground** define the background and foreground color of the buttons in the panel. * **NavAreaBackground** defines the background color of the panel.</ul> An important feature offered by the **HamburgerMenu** control, compared to the standard **SplitView** one, is built-in support to two categories of commands, similarly to the **PageHeader** control: * **PrimaryButtons** identifies the most used sections of the your application and they are placed at the top of the panel, right below the hamburger button. * **SecondaryButtons** identifies the sections of your app that the user will probably visit less frequently, like the Settings or the About page. They are displayed at the bottom of the panel, with a separator at the top.</ul> Inside both collections you can leverage a specific control offered by Template10 called **NavigationButtonInfo**, which will recreate for you the look & feel of the buttons you can find in the native application. Under the hood, it’s based on the **RadioButton** control, since it already implements a set of features that are ideal for our scenario (mutual choice between each button, highlight of the currently selected item, etc.) The following sample shows a complete definition of the **HamburgerMenu** control: <pre class="brush: xml;"><controls:HamburgerMenu x:Name="Menu" HamburgerBackground="#FFD13438" HamburgerForeground="White" NavAreaBackground="#FF2B2B2B" NavButtonBackground="#FFD13438" NavButtonForeground="White"> <controls:HamburgerMenu.PrimaryButtons> <controls:NavigationButtonInfo PageType="views:MainPage" ClearHistory="True"> <StackPanel Orientation="Horizontal"> <SymbolIcon Symbol="Home" Width="48" Height="48" /> <TextBlock Text="Home" Margin="12, 0, 0, 0" /> </StackPanel> </controls:NavigationButtonInfo> <controls:NavigationButtonInfo PageType="views:DetailPage"> <StackPanel Orientation="Horizontal"> <SymbolIcon Symbol="Calendar" Width="48" Height="48" /> <TextBlock Text="Calendar" Margin="12, 0, 0, 0" /> </StackPanel> </controls:NavigationButtonInfo> </controls:HamburgerMenu.PrimaryButtons> <controls:HamburgerMenu.SecondaryButtons> <controls:NavigationButtonInfo PageType="views:SettingsPage"> <StackPanel Orientation="Horizontal"> <SymbolIcon Symbol="Setting" Width="48" Height="48" /> <TextBlock Text="Settings" Margin="12, 0, 0, 0" /> </StackPanel> </controls:NavigationButtonInfo> </controls:HamburgerMenu.SecondaryButtons>
</controls:HamburgerMenu>
</pre>
The samples shows a menu with one primary command and one secondary command. Every button is represented with a **NavigationButtonInfo** control, which has a key property called **PageType**. You can use it to specify which is the page of your application connected to this button: when the user will tap on it, he will be automatically redirected to that page. Additionally, there are two other properties to customize the navigation experience: * **ClearHistory** is a boolean that, when it’s set to **true**, forces the cleanup of the back stack. It’s typically used with the main section of the application, to avoid circular navigation issues (when the user is on the main page of the app and the back button is still enabled). * **PageParameter** is helpful if you need to pass a parameter to the landing page, which can be retrieved using the **OnNavigatedTo()** method.</ul> The look & feel of the button is up to the developer: inside the **NavigationButtonInfo** control you can include any XAML control. In the sample you can see a definition that will help you to recreate the same look & feel of native apps: an icon (defined by the **SymbolIcon** control) and a label (defined with a **TextBlock** control). Here is how the previous code becomes when the app is running: [<img title="clip_image014" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image014" src="https://i2.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image014_thumb.jpg?resize=371%2C328" width="371" height="328" data-recalc-dims="1" />](https://i0.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image014.jpg) [<img title="clip_image016" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image016" src="https://i1.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image016_thumb.png?resize=369%2C338" width="369" height="338" data-recalc-dims="1" />](https://i2.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image016.png) The **HamburgerMenu** control, to work properly, needs a reference to the **NavigationService**, which is the service provided by Template10 to handle the navigation. This reference is configured in code-behind, thanks to the **NavigationService** property offered by the control: <pre class="brush: csharp;">public sealed partial class Shell : Page { public Shell(NavigationService navigationService) { this.InitializeComponent(); Menu.NavigationService = navigationService; } }
</pre>
In the next section we’re going to learn how to pass a reference to the **NavigationService** to the page that contains the **HamburgerMenu** control, like we’ve seen in the previous sample. ## ## Create the shell In the previous sections we’ve learned how, thanks to Template10, it’s easy to implement a navigation pattern based on the hamburger menu. However, we have a problem: the **HambrgerMenu** is just a control and, consequently, you need to add it to a page but, at the same time, you need to handle that every page of your application will reuse the same menu. Let’s introduce the **shell**, which is a special page of the application that will act as a container for the pages of the application. By using this approach, the **HamburgerMenu** control will be defined just once inside the shell and, consequently, we won’t have to include it in every page of the application. The first step is to create an empty page in our project and to repeat the steps we’ve already done in the previous section, which are including a **HamburgerMenu** control and connecting the **NavigationService**, like in the following sample: <pre class="brush: xml;"><Page x:Class="HamburgerSample.Views.Shell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:views="using:HamburgerSample.Views" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:Template10.Controls" x:Name="ThisPage" mc:Ignorable="d"> <controls:HamburgerMenu x:Name="Menu"> <controls:HamburgerMenu.PrimaryButtons> <controls:NavigationButtonInfo PageType="views:MainPage" ClearHistory="True"> <StackPanel Orientation="Horizontal"> <SymbolIcon Symbol="Home" Width="48" Height="48" /> <TextBlock Text="Home" Margin="12, 0, 0, 0" /> </StackPanel> </controls:NavigationButtonInfo> <controls:NavigationButtonInfo PageType="views:DetailPage" > <StackPanel Orientation="Horizontal"> <SymbolIcon Symbol="Calendar" Width="48" Height="48" /> <TextBlock Text="Calendar" Margin="12, 0, 0, 0" /> </StackPanel> </controls:NavigationButtonInfo> </controls:HamburgerMenu.PrimaryButtons> <controls:HamburgerMenu.SecondaryButtons> <controls:NavigationButtonInfo PageType="views:SettingsPage"> <StackPanel Orientation="Horizontal"> <SymbolIcon Symbol="Setting" Width="48" Height="48" /> <TextBlock Text="Settings" Margin="12, 0, 0, 0" /> </StackPanel> </controls:NavigationButtonInfo> </controls:HamburgerMenu.SecondaryButtons> </controls:HamburgerMenu> </Page>
</pre>
<pre class="brush: csharp;">public sealed partial class Shell : Page { public Shell(NavigationService navigationService) { this.InitializeComponent(); Menu.NavigationService = navigationService; } }
</pre>
Now we need to: 1. Configure the page we’ve just created as container for all the page of our application, by replacing the standard frame. * Pass to the page a reference to the **NavigationService** object</ol> Both operations can be achieved in the **BootStrapper** class: we’re going to use the **OnInitializeAsync()** method, which is performed right before the app triggers the navigation to the main page. <pre class="brush: csharp;">sealed partial class App : BootStrapper { public App() { this.InitializeComponent(); } public override Task OnInitializeAsync(IActivatedEventArgs args) { var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Include); Window.Current.Content = new Views.Shell(nav); return Task.FromResult<object>(null); } public override Task OnStartAsync(BootStrapper.StartKind startKind, IActivatedEventArgs args) { NavigationService.Navigate(typeof(Views.MainPage)); return Task.FromResult<object>(null); } }
</pre>
The first step is to use the **NavigationServiceFactory** method to retrieve the proper reference to the **NavigationService**. This way, we can pass it as a parameter when we create a new instance of the **Shell** page. Then we assign this instance to the **Window.Current.Content** property, which holds a reference to the main frame of the application, which will act as a container for the pages. In a standard application, this property is simply set with a new instance of the **Frame** class. Thanks to this line of code, the application won’t use anymore an empty frame as a container for your pages, but the **Shell** page, which contains the **HamburgerMenu** definition. The final result will be that all the pages of your application will share the same menu we have defined in the **Shell** page. # # HamburgerMenu and PageHeader: the dynamic duo The **PageHeader** and **HamburgerMenu** controls have been designed to work together. The best visual layout, in fact, can be achieved when the various sections in a hamburger menu are handled with a page that has a **PageHeader** control to define the header. Moreover, both controls supports the adaptive layout, which is the new approach introduced in Windows 10 to help developers building a single binary package that can runs on every platform (vice versa, on Windows and Windows Phone 8.1 you needed to create and publish two different packages). **Adaptive layout** is an approach which is already widely used in the web world and it simply means that the user interface has to properly react to the changes in the window’s size, so that the app can always offer the best user experience, regardless if it’s running on a mobile phone or on a console. Both controls implements this approach to optimize the user experience: * By default, the **PageHeader** control doesn’t add any margin to the text of the header. When the app’s windows is wide enough, the **HamburgerMenu** control will always be visible in minimal mode (which means that the icons will always be visible, while the labels will be displayed only when the panel is open). Consequently, there’s no need to artificially add a margin in the **PageHeader** control: the hamburger button of the menu already takes care of it. * When the size of the window is smaller (for example, on a phone) there isn’t enough space to keep the menu icons always visible. Consequently, the panel is completely hidden: only the hamburger button will be visible. In this scenario, the **PageHeader** control adds a 48px margin on the left, to avoid that the header’s text overlaps with the button.</ul> This behavior is automatically handled by both controls. However, you have the chance to define which is the size of the window that should trigger the two visual states, by using the **VisualStateNarrowMinWidth** and **VisualStateNormalMinWidth** properties. Take a look at the following sample: <pre class="brush: xml;"><controls:PageHeader Text="Main page" Frame="{x:Bind Frame}" VisualStateNarrowMinWidth="0" VisualStateNormalMinWidth="700" />
</pre>
With this configuration: * When the width of the window is between 0 and 700, the control applies the **VisualStateNarrow** visual state, which is the minimal one (the panel is hidden and the header’s text is shifted). * When the width of the window is bigger than 700, instead, the control applies the **VisualStateNormal** visual state, which is the standard one (the panel is visible in minimal mode and a shift of the header’s text isn’t required).</ul> The same properties are available also in the **HamburgerMenu** control: of course, to get the best result, it’s important that the two properties are set in the same way on both controls. The following images will help you to understand better the difference between the two states: the first one is the normal state, the second one is the narrow state. [<img title="clip_image017" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image017" src="https://i1.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image017_thumb.png?resize=379%2C347" width="379" height="347" data-recalc-dims="1" />](https://i0.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image017.png) [<img title="clip_image019" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image019" src="https://i1.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image019_thumb.png?resize=376%2C418" width="376" height="418" data-recalc-dims="1" />](https://i0.wp.com/wp.qmatteoq.com/wp-content/uploads/2015/09/clip_image019.png) If you want to disable this behavior for the **PageHeader** control (for example, because you aren’t providing a hamburger menu based navigation experience and, as such, the shift of the header’s text can break your layout) it’s enough to set the **VisualStateNarrowMinWidth** property to –1. # # # # Wrapping up In this post we’ve learned how to use the custom controls offered by Template10. In the next post, instead, we’ll see more C# code, since we will focus on how Template10 can make easier the implementation of the MVVM pattern. As a reminder, you can find Template10 on GitHub (<http://github.com/Windows-XAML/Template10/>). The repository contains also a set of samples to start playing with the controls described in this post. Happy coding!
in
- The control, thanks to the Frame property, is connected to the navigation’s frame. Consequently, it’s able to automatically detect if there are pages in the back stack so that if it’s empty (for example, because you’re in the main page), the button will always be hidden.
-
Template10: a new template to create Universal Windows apps – The basics
When you launch Visual Studio 2015 to create a Universal Windows app for Windows 10 for the first time, the first thing you notice is that the number of available templates is very low. If, when it comes to Windows / Windows Phone 8.1 development, Visual Studio 2013 offered many templates to quickly implement the most used layouts (Hub, Pivot, etc.), in Visual Studio 2015 we have just one template called “Blank app”.
The reason of this choice is that, in the past, the standard templates were used by the developers without very good skills in developing the user experience of an application (like me ) to make the job easier and to avoid to create the user interface from scratch. The downside of this approach is that, during the course of time, it leads many developers to publish a lot of applications that looked very similar to each other. Consequently, Microsoft has decided, with Windows 10, to leave more freedom to the developers and to avoid forcing them to adopt a specific design patter. It’s important to highlight, however, that this doesn’t mean that you can do whatever you want when it comes to create the user interface, without following any criteria. Providing a great user experience is still one of the key pillars to create a successful app! As such, I strongly suggest to read the official guidelines to design Universal Windows apps on the Dev Center: https://dev.windows.com/en-us/design
The new blank template provided by Visual Studio 2015 is very simple and it’s the perfect starting point for every application. However, sometimes, especially when you need to work on a complex project, it can be even too simple. When we need to handle advanced scenarios (like using the MVVM pattern or managing the state of the page) we need to create all the required infrastructure.
To make the life the developers easier, a team of Microsoft people, lead by Jerry Nixon (a Technical Evangelist very well known for his series of MVA trainings about Windows 10 development) have started to work on an advanced template called Template10. It’s an open source project, available on GitHub at https://github.com/Windows-XAML/Template10 and, as such, you’re more then welcome to give your contribute, by helping with the documentation or by making some enhancements and submitting a pull request.
The project is still evolving, but the goal is very clear: Template10 wants to become the preferred choice for Universal Windows apps developers, independently from the development approach they prefer (code behind, MVVM, etc.) or from the toolkits and libraries they already use in their applications. If you want to learn more about the project, you can read the official FAQ on https://github.com/Windows-XAML/Template10/wiki/Questions. In the near future, Template10 will be released as a NuGet package and as a Visual Studio extension. This way, you’ll be able to use it as a starting point for your app directly from the New project menu in Visual Studio 2015. Meanwhile, however, even if the main library that defines the template’s components is considered stable and ready for production, it’s available only on GithHub. Let’s see which are the required steps to start creating a new Universal Windows app using Template 10.
UPDATE: Template10 is now available also as NuGet package: http://www.nuget.org/packages/Template10/1.0.2.2-preview. However, to find and install it, you’ll need to enable in the NuGet Package Manager UI the Include prerelease options, since the package is still in beta.
This post is just the first of a series: in this one we’re going to see the basic concepts. In the next ones, we’ll see some more advanced topics like the available controls or the MVVM pattern.
###
Create the first project
The first step is to clone the GitHub repository. We can achieve this goal using the tools provided directly by Visual Studio 2015.
- Open the window called Team Explorer. As default behavior, it’s placed on the right side of the screen, in the same section where you have access to the Solution explorer’s window.
- You’ll find a section labeled Local Git Repositories, which lists all the Git repositories on your computer. Press the Clone button.
- In the first field (the one with the yellow background) you need to specify the URL of the GitHub repository, which is https://github.com/Windows-XAML/Template10
- In the second field, instead, you need to set the local path on your computer where you want to clone the project.
- Now press the Clone button: Visual Studio will take care of downloading the project and copying it on your computer.</ol>
From now on, by using Team Explorer, you’ll be able to quickly access to the repository. By using the Sync option you’ll have the chance to keep the local repository up to date with the latest version of the library.
A good starting point for a new Universal Windows app based on Template10 is to use the Blank project, which is stored inside the Templates (Project) folder. This project already provides the basic infrastructure required by Template10 to work properly. However, in this post we’re going to start with an empty project and to manually configure Template10: this way, it will be easier to understand how it works under the hood.
Let’s start by creating a new Universal Windows app with the Blank app template provided by Visual Studio. Then, let’s right click on the solution in Solution Explorer and choose Add existing project. We’ll have to look for the folder where we’ve cloned the GitHub repository and, specifically, we’ll have to find the project named Template10Library: you’ll find in the folder with the same name and it’s defined by the Template10Library.csproj file. Once you’ve added the project to your solution, it’s time to add a reference to Template10 in our app. Just right click on the project of the application, choose Add reference and, in the list, choose the Template10 project. Now we are ready to start writing some code!
###
The bootstrapper
The App class is the starting point of every Universal Windows app: its goal is to initialize the main window of the application with its frame, which acts as a container of all the pages of the application and provides the necessary infrastructure to handle the navigations. The base structure of the App class (stored in the App.xaml.cs file), however, can be a little bit confusing, especially for new developers. You’ll find a lot of fixed code, which is part of the standard initialization and, as such, it creates just “noise”, since you’ll probably never change it. Another weak point is the application’s lifecycle management. The App class offers different event handlers to manage the different application’s state (launching, suspending, resuming, etc.) but, based on the activation’s type, you can have multiple entry points. Template10 makes the initialization of the app easier to understand and to use by providing a bootstrapper, which is a class that replaces the App one and that simplifies the code. The first step to use is to replace the App class with the BootStrapper one, which is included in the Template10.Common namespace. Here is a sample definition:
<common:BootStrapper x:Class="BasicSample.App" xmlns:common="using:Template10.Common" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
- In the second field, instead, you need to set the local path on your computer where you want to clone the project.
- In the first field (the one with the yellow background) you need to specify the URL of the GitHub repository, which is https://github.com/Windows-XAML/Template10
- You’ll find a section labeled Local Git Repositories, which lists all the Git repositories on your computer. Press the Clone button.
</common:BootStrapper>
</pre>
You can notice that the main **App** node has been replaced with the **BootStrapper** one. Consequently, you will have also to update the code-behind class (the **App.xaml.cs** file), so that the **App** class inherits from the **BootStrapper** one, like in the following sample: <pre class="brush: csharp;">sealed partial class App : Template10.Common.BootStrapper { public App() { InitializeComponent(); }
}</pre>
Here is, instead, how a complete definition of the **BootStrapper** class looks like: <pre class="brush: csharp;">sealed partial class App : Template10.Common.BootStrapper { public App() { InitializeComponent(); } public override Task OnStartAsync(StartKind startKind, IActivatedEventArgs args) { NavigationService.Navigate(typeof(MainPage)); return Task.FromResult<object>(null); } }
</pre>
You can immediately notice how, compared to the standard **App** class, the code is much more simple to understand. The core is the **OnStartAsync()** method, which is the starting point of the application, regardless from the activation’s scenario. No matter if the app has been opened using the main tile, a secondary tile or from a toast notification, the **OnStartAsync()** method will always be invoked to let you, as developer, handling the main navigation. In the simplest scenario (your app doesn’t have secondary tiles or doesn’t support secondary activation entries), the method will look like the one in the sample: it simply takes care of redirecting the user to the main page of the application. The second operation is just a workaround to support asynchronous code inside this method. To properly support async / await operations, the method has been configured to return a **Task** object; however if, like in this case, you don’t have the requirement to perform any asynchronous operation, we simply return an empty Task, so that the code can compile. The main advantage of the **OnStartAsync()** method is that the bootstrapper, under the hood, always takes care of preparing the Frame, which is required to handle the rendering and the navigation of the pages of the application. The standard **App** class, instead, takes care of initializing the Frame only in the main entry point (the **OnLaunched()** event handler), leaving you to do all the “dirty work” in case the app has been opened from a different activation point. To help you understanding better this approach, here is a sample bootstrapper used to handle the activation from a secondary tile: <pre class="brush: csharp;">sealed partial class App : Template10.Common.BootStrapper { public App() { InitializeComponent(); } public override Task OnStartAsync(StartKind startKind, IActivatedEventArgs args) { AdditionalKinds cause = DetermineStartCause(args); if (cause == AdditionalKinds.SecondaryTile) { LaunchActivatedEventArgs eventArgs = args as LaunchActivatedEventArgs; NavigationService.Navigate(typeof (DetailPage), eventArgs.Arguments); } else { NavigationService.Navigate(typeof (MainPage)); } return Task.FromResult<object>(null); } }
</pre>
The code is very simple to understand. Thanks to the internal method **DetermineStartCause()** we are able to determine which is the activation point of the app and to redirect the user to the most appropriate page. In the sample we are handling the scenario where the tap on a secondary tile redirects the user to a specific item of the application (like a category of news): in case the activation’s cause is **AdditionalKinds.SecondaryTile**, we retrieve the tile’s arguments (thanks to the **Arguments** property) and we pass it to the page called **DetailPage**. In case, instead, the application has been regularly launched using the main tile, the user is simply redirected to the main page. With the same approach we can handle all the other activation’s scenarios: from a toast notification, from a uri, from a sharing contract, etc. In this case, the **DetermineStartCause()** method will return you the **Other** value of the **AdditionalKinds** enumerator. To properly determine what’s happened, we need to use the **Kind** property of the activation’s parameter which type is **IActivatedEventArgs**. Inside the bootstrapper class you have also the chance to override three other methods, which can be useful to handle special scenarios. 1. **OnInitializeAsync()** is invoked when the app is initialized, right before calling the **OnStartAsync()** method. It’s useful if you have any service or feature that requires to be initialized at startup (for example, analytics services like Application Insights). * **OnResuming()** has the same purpose of the method with the same name of the standard **App** class and it’s invoked when the application is resumed after it has been suspended. Typically, you’re not required to handle this event; the reason is that it’s triggered only when the application has been resumed from a suspension state and not from a termination. As such, since the process was kept in memory, you don’t have to retrieve the state you may have previously saved, since it’s still there. This method can be useful if you need to refresh the data in case, for example, the user has resumed the application after a while. * **OnSuspending()** is invoked when the application is suspended. Typically, this method is used to save the application’s state, so that it can be restored in the case the app is terminated by the operating system due to low resources. However, as we’re going to see in the next posts, with Template10 this operation is not required: the bootstrapper is able to take care of this scenario automatically.</ol> # # Extended splash screen The splash screen is a static image (placed in the Assets folder of your project) which is displayed to the user during the app’s initialization phase. Once the operation is completed, the splash screen is removed from the screen and the Frame redirects the user to the main page of the app. As best practices, the app’s initialization should be as quickest as possible: if the operation isn’t completed within 10 seconds, the app will be terminated by the OS. However, it’s not uncommon that the app may need more than 10 seconds to be ready, especially if the application’s data has to be downloaded from a remote source (like a REST service). To avoid the app to be terminated by the OS, one of the best practices is to avoid loading the data in the App class, but to perform it directly in the main page of the app. This way, the initialization phase will be very quick and the main page will immediately take control of the app. However, since the app is now ready and the initialization operation is completed, the OS won’t try to kill the app anymore, even if the main page would need more than 10 seconds to load all the data. This approach works great, but often it doesn’t provide a good user experience: the user is redirected to the main page of the app which, however, will be empty and it will display just a loading message, until all the data is ready to be displayed. To improve the UX many applications have introduced the concept of **extended splash screen**: after that the basic initialization is completed, the user will be redirected to another page of the app which will look exactly like the splash screen. The difference here is that, since we aren’t talking anymore about a static image but we’re dealing with a real page, we can add additional UI elements to notify to the user that a loading operation is in progress (like a **ProgressBar** or a **ProgressRing** control). If you want to learn more about this topic, the MSDN documentation offers some guidance on how to implement an extended splash screen at <https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868191.aspx> As you can see in the document, there’s a bit of work to do, other than just creating the page that will act as extended splash screen. Template10 simplifies this approach, by offering a class that takes care of handling the transition between splash screen –> extended splash screen –> first page of the app. Let’s see how to use it. The first step is to create the splash screen itself, by adding a new **UserControl** to your application. You have the freedom to add everything you want in this control. However, since the goal of this control is to hide the transition from the static splash screen, typically the first thing you want to add is an **Image** control that displays the same image used as splash screen. The following sample shows a control where the image is placed inside a **Canvas** with the same background color of the image. In addition, we add a **ProgressRing** control to notify to the user that a loading operation is in progress. <pre class="brush: xml;"><UserControl x:Class="BasicSample.Views.SplashScreenView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid> <Canvas x:Name="MyCanvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="#0971C3"> <Image x:Name="MyImage" Stretch="None" Source="/Assets/SplashScreen.png" /> </Canvas> <ProgressRing VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="50" Height="50" IsActive="True" Foreground="White" Margin="0, 0, 0, 100"/> </Grid> </UserControl>
</pre>
In code behind we use the **SplashScreen** class (which returns some important information about the image, like the size and the position) to configure the **Image** control in the same way. This way, the user won’t notice the transition from the real splash screen to the extended one. <pre class="brush: csharp;">public sealed partial class SplashScreenView : UserControl { public SplashScreenView(SplashScreen splashScreen) { this.InitializeComponent(); Action resize = () => { MyImage.Height = splashScreen.ImageLocation.Height; MyImage.Width = splashScreen.ImageLocation.Width; MyImage.SetValue(Canvas.TopProperty, splashScreen.ImageLocation.Top); MyImage.SetValue(Canvas.LeftProperty, splashScreen.ImageLocation.Left); }; Window.Current.SizeChanged += (s, e) => resize(); resize(); } }
</pre>
The resize and reposition operations are defined into an **Action** which, other than being executed when the user control is initialized, is connected also to the **SizeChanged** event, which is triggered when the size of the app’s window changes. It’s required since, when the app runs on a desktop, the user is able to resize the window at any time and, consequently, the splash screen needs to readapt itself. Now that we have created our custom control, we are ready to use it as a splash screen, thanks to the **SplashFactory** class provided by the **BootStrapper:** <pre class="brush: csharp;">public App() { InitializeComponent(); SplashFactory = e => new SplashScreenView(e); }
</pre>
**SplashScrenView** is the name of the UserControl we have just created, while **e** is the instance of the **SplashScreen** class that we have passed to the control’s constructor (it’s the one we’ve used to calculate the size and the position of the image). Now we’re ready to test it: as soon as the application takes more than a few seconds to initialize, the user will be redirected to the extended splash screen and, only at the end of the loading process, to the main page of the app. If you want to simulate a heavy data loading to test the splash screen, you can add a delay in the **OnStartAsync()** method, before the navigation to the main page is performed, like in the following sample: <pre class="brush: csharp;">sealed partial class App : Template10.Common.BootStrapper { public App() { InitializeComponent(); SplashFactory = e => new SplashScreenView(e); } public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args) { await Task.Delay(TimeSpan.FromSeconds(5)); NavigationService.Navigate(typeof(MainPage)); } }
</pre>
Once the initialization is completed, the bootstrapper will invoke the **OnStartAsync()** method and, until it’s triggered the navigation to the main page of the page, the extended splash screen will be displayed. In this sample, since we’ve added a 5 second delay, the splash screen will be displayed for 5 seconds before the user will see the main page. # Navigation Another important feature offered by Template10 is the automatic handling of the page stack. If you already have some experience in developing Windows Store apps for Windows and Windows Phone 8.1, you’ll know that navigation management is one of the main differences between the two platforms. On Windows Phone, you don’t have to add any visual element in the user interface to allow the user to go back to the previous page of the app, since every device has a hardware Back button. However, the same doesn’t apply on Windows, since there is no Back button on a desktop or on a tablet. Windows 10 has changed this behavior; also the desktop version, in fact, offers a build-in management of the Back button, by providing a virtual back button which can be placed in different positions, based on the scenario: 1. If the app is running in desktop mode, the Back button will be added in the app’s chrome, on the top right corner. * If the app is running in tablet mode, the Back button will be added in the system bar, between the Start and Cortana buttons.</ol> [<img style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; padding-right: 0px; border-top-width: 0px" border="0" alt="" src="https://i2.wp.com/blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-87-58/4118.3.png?resize=428%2C593" width="428" height="593" data-recalc-dims="1" />](https://i1.wp.com/blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-87-58/4118.3.png) [<img border="0" alt="" src="https://i0.wp.com/blogs.msdn.com/resized-image.ashx/__size/300x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-87-58/6318.2.png?resize=441%2C147" width="441" height="147" data-recalc-dims="1" />](https://i1.wp.com/blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-87-58/6318.2.png) Typically, in a standard application, it’s up to the developer to handle this feature, by using the **SystemNavigationManager** class, which provides the required APIs to handle the visibility of the button or the navigation events. Template10, instead, automatically enables this management on every device family. Consequently: * When the application is running on the desktop and the page stack isn’t empty, on the top right corner the virtual Back button will be visible. If, instead, the stack is empty (for example, because the user is on the first page), the button will be automatically hidden. * When the application is running on a mobile device, pressing the hardware Back button will automatically redirect the user to the previous page of the app or, if the stack is empty, to the Start screen of the device.</ul> If we want to disable this behavior (for example, because we want to handle the navigation by ourselves, by adding a button in the UI) we can set the **ShowShellButton** property of the **BootStrapper** class to **false**: <pre class="brush: csharp;">public App() { InitializeComponent(); ShowShellBackButton = false; }
</pre>
When this option is disabled, you will notice that the virtual Back button in the app’s chrome will never be displayed. # # In the next post In this post we’ve learned some of the basic concepts of Template10 and which are some of the features that we can start to use, right away, to improve our application. We’ve just scratched the surfaced and, in the next posts, we’re going to see the “true power” of Template10, especially when it’s used in combination with the MVVM pattern. If, in the meanwhile, you want to start doing experiments with Template10, you can use the samples that are provided on the GitHub repository. Happy coding!
in
- Open the window called Team Explorer. As default behavior, it’s placed on the right side of the screen, in the same section where you have access to the Solution explorer’s window.
-
The new background features in Windows 10
If you already have some experience in developing Universal Windows apps for Windows and Windows Phone 8.1, you should already be familiar with the “application lifecycle” concept. Compared to the traditional desktop model, where the application lifecycle is quite simple (basically, one app is able to run and perform tasks until it’s closed), in the mobile world things are a bit different. A mobile device like a smartphone, in fact, needs to handle many requirements which aren’t common in the desktop world, like battery usage, limited available memory, etc.
Consequently, Universal Windows apps (both on 8.1 and 10) use a different lifecycle model, which can be summarized with the following image:
__
When an application is opened, it enters into a state called running: in this state, it’s able to use memory, CPU, sensors and whatever feature is available on the device. As soon as the app is suspended (because the user has pressed the Start button or has tapped on a notification sent by another application), after 5 seconds the process is “frozen” in memory. It means that the process will be kept in the device’s RAM memory, but it won’t be able to perform any operation. As such, every device’s resource (CPU, the camera, sensors, etc.) will be available to every other application that the user will decide to launch next. When the user decides to return to our application, the resuming event is triggered: the process is awaken and the application can use again all the device’s resources.
It may happen, however, that the resources are running low: for example, the user starts to open a lot of applications or he may have suspended one or two apps which use a lot of memory (like a game). In this case, when a new application is opened, the device may not have enough memory to manage it: consequently, the operating system has the chance to terminate the older applications to free some memory. In this scenario, it’s the developer’s job to save the state of the application, during the suspension phase, in order to restore it in case the app is reopened after a termination. The goal of this approach is to give to the user the impression that the app has never been closed: the termination by the operating system should be completely transparent for him.
###
Perform operations in background: background tasks
As you can imagine after reading how the application’s lifecycle works, Universal Windows apps don’t have the chance to perform operations when they’re suspended. The process, in fact, is “frozen” and, as such, it can’t perform any activity which involves the usage of CPU, network, etc.
To allow developers to handle the requirement to perform, somehow, some operations even when the app is suspended, the Windows Runtime has introduced the concept of background task. They are separate projects from the main one that contains the application, but they belong to the same solution and they access to the same app’s context (so, for example, a background task can access to the same local storage used by the application). Background tasks are usually made by a single class, which contains the code that is executed when it’s scheduled by operating system, even if the main application isn’t running.
Here is a sample definition of a background task:
using Windows.ApplicationModel.Background; namespace Tasks { public sealed class ExampleBackgroundTask : IBackgroundTask { public void Run(IBackgroundTaskInstance taskInstance) { } } }
A background task is made by a class, which implements the IBackgroundTask interface and manages a method called Run(), which is invoked when the task is activated.
Background tasks are projects which type is Windows Runtime Component and they’re connected to the concept of trigger, which are events that you can subscribe to invoke a background task. There are many types of triggers in Windows Runtime: they can be used to manage periodic requirements (for example, if the task needs to run every 30 minutes), system events (for example, the user has locked / unlocked the device) or the communications with other devices (there is a set of triggers to interact with Bluetooth Low Energy devices).
I won’t go deep about background tasks in this post, since the way they work has unchanged moving from Windows 8.1 to Windows 10. You will find a wide set of new triggers, but the base concepts that drive the development are the same. If you’re interested into this subject, you can refer to the MSDN documentation which is available at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977056.aspx
Keep the application active when it’s suspended
The new feature added in Windows 10, which I’m going to detail in this post, is the ExtendedExecutionSession class, which can be used to support two new scenarios:
- The application needs to save some data or complete a pending operation before it’s suspended and the 5 seconds timeframe isn’t enough.
- The application needs to continue the execution even when it’s suspended, for example to keep track of the user’s position (a fitness app, a turn by turn navigator, etc.)</ol> Let’s see how to handle both scenarios.
#### #### Complete a pending operation This scenario is managed inside the event that the **App** class provides to handle the suspension. In the standard definition of this class (which is declared inside the **App.xaml.cs** file) you’ll find the following lines of code: <pre class="brush: csharp;">private void OnSuspending(object sender, SuspendingEventArgs e) { var deferral = e.SuspendingOperation.GetDeferral(); deferral.Complete(); }
</pre>
By default, this code doesn’t do anything: it just asks for a deferral, which is a way to handle asynchronous operations inside the suspension event. Without using the deferral, the beginning of an asynchronous operation may cause the immediate termination of the app by the operating system, since it’s performed on a different thread than the main one. Inside the **OnSupending()** method we can use the **ExtendedExecutionSession** class to ask for more time, so that we have the chance to complete the running operation. Here is a sample code: <pre class="brush: csharp;">private async void OnSuspending(object sender, SuspendingEventArgs e) { var deferral = e.SuspendingOperation.GetDeferral(); var extendedSession = new ExtendedExecutionSession(); extendedSession.Reason = ExtendedExecutionReason.SavingData; extendedSession.Description = "Complete synchronization"; ExtendedExecutionResult result = await extendedSession.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Allowed) { UploadCompleteData(); } else { UploadBasicData(); } deferral.Complete(); }
</pre>
When we create a new **ExtendedExecutionSession** instance, we have to define: 1. The reason why we need that the running operation continues even after the suspension. In our scenario, we need to use the **SavingData** value of the **ExtendedExecutionReason** enumartor. * A description that briefly summarize the operation we’re going to perform. It’s a simple string.</ol> Then we can call the **RequestExtensionsAsync().** As you can imagine from the name of the method, this operation doesn’t guarantee that the request will be accepted; the operating system could decide to deny it, according to the available resources. Consequently, it’s very important to check the result of the operation, which type is **ExtendedExecutionResult.** Only if the result is **Allowed**, we are authorized to execute an operation that could take more than 5 seconds to be completed; otherwise, instead, we need to apply a workaround to satisfy the 5 seconds constraint. It’s important to remind that this approach doesn’t allow an infinite execution time: in case resources are running low, the operating system could terminate the running activity. ### #### Keep the application running in background The second feature provided by the **ExetendedExecutionSession** class offers a bit more flexibility: when the application is suspended, in fact, it will be kept alive in background: the process won’t be frozen, but it will be able to keep performing operations, handle events, etc. It’s like if the application in foreground, except that it isn’t visible to the user. It’s a feature which can be very useful for location tracking apps: for example, a fitness app could leverage this approach to track the user’s run even if the phone is locked and placed in the user’s pocket. This is the reason why the **ExtendedExecutionSession** class identifies this approach by assigning the **LocationTracking** value to the **Reason** property. Moreover, this feature requires that the **Location** capability is declared in the manifest file. To be honest, the operating system doesn’t force you to use the location APIs to use this feature: however, it’s important to keep in mind that the user, in the Store page, will see that your application is accessing to the user’s location, even if you aren’t actually doing it. As such, think twice before choosing to go down this path. The main difference with the previous scenario (completing a pending operation) is the position in code when the **ExtendedExceutionSession** class is used: if, in the code sample we’ve previously seen, we used it inside the **OnSuspending()** method of the **App** class, now instead we need to ask the permission to the operating system to run in background as soon as possible. Typically, this is done when the main page of the application is loaded, so the **OnNavigatedTo()** or the **Loaded**() ****events are good candidates. Here is a code sample: <pre class="brush: csharp;">protected override async void OnNavigatedTo(NavigationEventArgs e) { if (e.NavigationMode == NavigationMode.New) { var extendedSession = new ExtendedExecutionSession(); extendedSession.Reason = ExtendedExecutionReason.LocationTracking; extendedSession.Description = "Location tracking"; ExtendedExecutionResult result = await extendedSession.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Allowed) { Debug.WriteLine("Background execution approved"); } else { Debug.WriteLine("Background execution denied"); } } }
</pre>
The first line of code makes sure that the initialization is made only when the navigation mode is **New**, which means that the page is loaded for the first time: this way, we can avoid that the initialization is repeated every time that the user, from an inner page, navigates back to the main one. If we try to initialize the **ExtendedExecutionSession** object multiple times, in fact, we’ll get an exception. The rest of the code is pretty much the same we’ve seen in the previous scenario, except that: 1. We’re setting the **Reason** property of the **ExtendedExecutionSession** class to **LocationTracking**. 2. Also in this case it’s useful to check the result of the **RequestExtensionAsync()** method, but only for logging or warning purposes. In fact, in case the app is allowed for background execution, we won’t have anything special to do: the app will simply continue to run, like if it has never been suspended. It’s important to highlight that one of the causes that may lead to a denied execution is that the **Location** capability is missing in the manifest file. #### It’s important to highlight that, even if the application is indeed running in background, it’s not able to interact with the UI thread: if you need to show any information to the user, you need to rely on the features provided by the platform, like notifications. The following sample code shows how to leverage notifications in a background execution scenario: <pre class="brush: csharp;">public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } protected override async void OnNavigatedTo(NavigationEventArgs e) { if (e.NavigationMode == NavigationMode.New) { var extendedSession = new ExtendedExecutionSession(); extendedSession.Reason = ExtendedExecutionReason.LocationTracking; extendedSession.Description = "Location tracking"; ExtendedExecutionResult result = await extendedSession.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Allowed) { Debug.WriteLine("Background execution approved"); } else { Debug.WriteLine("Background execution denied"); } Geolocator locator = new Geolocator(); locator.DesiredAccuracyInMeters = 0; locator.MovementThreshold = 500; locator.DesiredAccuracy = PositionAccuracy.High; locator.PositionChanged += Locator_PositionChanged; } } private void Locator_PositionChanged(Geolocator sender, PositionChangedEventArgs args) { string xml = $@" <toast activationType='foreground' launch='args'> <visual> <binding template='ToastGeneric'> <text>This is a toast notification</text> <text>Latitude: {args.Position.Coordinate.Point.Position.Latitude} - Longitude: {args.Position.Coordinate.Point.Position.Longitude}</text> </binding> </visual> </toast>"; XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); ToastNotification notification = new ToastNotification(doc); ToastNotifier notifier = ToastNotificationManager.CreateToastNotifier(); notifier.Show(notification); } }
</pre>
After subscribing for background execution, we initialize the **Geolocator** class and we subscribe to the **PositionChanged** event, which is triggered every time the geo localization services detects a new position. When this event happens, we prepare the payload of a toast notification with the info about the detected longitude and latitude and then we display it, using the **ToastNotification** and **ToastNotificationManager** classes. We can easily test this application using the Windows 10 Mobile emulator: just open the app and, by leveraging the Location simulator in the Additional tools, just place a pushpin in a random map location. Every time you’ll perform this operation, you’ll see a notification with the coordinate of the selected place. However, since we requested background execution, the **PositionChanged** event handler will be triggered even if the app is suspended. Let’s repeat the same test (placing random pushpins on the map) but, before, suspend the app: you’ll notice that the notifications will be displayed anyway, since the app is indeed still running, even if it’s not visible. As you can see, this features allows a lot of flexibility; consequently, there are some constraints to prevent that an app could negatively affect the battery life or the performances of the devices. First, only one application at a time can leverage the background execution; if the user opens another application that uses the same feature, the already running one will be stopped and suspended. In addition, also in this case the operating system continuously monitors the available system resources: if they are running low, it will be able to kill our running app and suspend it. ### ### Wrapping up The new background execution feature is very simple to manage but, at the same time, very powerful and it opens up scenarios that it wasn’t possible to support in a Windows or Windows Phone 8.1 application. You can find with a sample project that shows how to use the **ExtendedExecutionSession** API on my GitHub repository [https://github.com/qmatteoq/Windows10-Samples](https://github.com/qmatteoq/Windows10-Samples "https://github.com/qmatteoq/Windows10-Samples"). Happy coding!
in
- The application needs to save some data or complete a pending operation before it’s suspended and the 5 seconds timeframe isn’t enough.
subscribe via RSS