Category Archives: Universal App.

Adaptive triggers in a universal app.

Adaptive triggers are part of the Universal Windows application and part of Windows 10.

With a universal app. you can begin writing an application which can target multiple Windows platforms/devices, for example mobile, tablet and desktop.

When writing UI code for a variety of devices you’ll come across the problem where, for example, a button on a desktop needs to be place elsewhere when used on a mobile phone and so on.

Adaptive triggers allow us to customize layout based upon the dimensions of the device we’re running on. But wait ! This statement is slightly misleading. The trigger actually has nothing to do with the device and everything to do with the Window size of the application on the device. So in reality an AdaptiveTrigger is more like a responsive design feature in that when the Window is expanded, it’s possible one layout is used and when the Window is reduce in size maybe another layout is used.

To define an AdaptiveTrigger we use the VisualStateManager and create StateTriggers, which contain our AdaptiveTrigger(s).

For example, let’s define VisualState and AdapterTriggers for a desktop with a minimum width of 1024 pixels and a phone with minimum width of 320 pixels and we’ll a the button display differently for each device.

Note: the x:Name is there just for descriptive purposes in this example.

<Grid>
   <VisualStateManager.VisualStateGroups>
      <VisualStateGroup>
         <VisualState x:Name="DeskTop">
            <VisualState.Setters>
               <Setter Target="button.(FrameworkElement.HorizntalAlignment)" Value="Left" />
            </VisualState.Setters>
            <VisualState.StateTriggers>
              <AdaptiveTrigger MinWindowWidth="1024" />
           </VisualState.StateTriggers>
         </VisualState>
         <VisualState x:Name="Phone">
            <VisualState.Setters>
               <Setter Target="button.(FrameworkElement.HorizntalAlignment)" Value="Right" />
            </VisualState.Setters>
            <VisualState.StateTriggers>
              <AdaptiveTrigger MinWindowWidth="320" />
           </VisualState.StateTriggers>
         </VisualState>
      </VisualStateGroup>
   </VisualStateManager.VisualStateGroups>
</Grid>

Enumerating available devices in UWP

In my previous post (Displaying the device picker in a UWP application) I showed how to reuse the UWP device picker flyout within an application.

However, it’s possible that the developer would prefer to offer devices in some alternate UI or, of course, simply locate a known device for an application to use. In the previous post I looked at filtering for Bluetooth devices and those are what I’m after for a little application I’m writing in which I do not require the DevicePicker UI.

Filtering

Before I get into code to enumerate the devices, I’ll first expand on the lines of code from my previous post, that look like this

BluetoothDevice.GetDeviceSelectorFromPairingState(false)

Each of the lines like this one actually returns a string which is an Advanced Query Syntax (AQS) language query. So for example this line will produce the following string (formatted to make it more readable)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#False OR
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#True)

For completeness, here’s the results of each of the other GetDeviceSelectorFromPairingState calls

BluetoothLEDevice.GetDeviceSelectorFromPairingState(false)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{BB7BB05E-5972-42B5-94FC-76EAA7084D49}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#False OR 
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#True)

BluetoothLEDevice.GetDeviceSelectorFromPairingState(true)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{BB7BB05E-5972-42B5-94FC-76EAA7084D49}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True OR 
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#False)

BluetoothDevice.GetDeviceSelectorFromPairingState(true)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True OR 
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#False)

Hence we could now create our own AQS query to search for devices.

See Using Advanced Query Syntax Programmatically for more information on AQS.

Enumerating over devices (simple approach)

A simple approach to enumerating over all the available devices is to use the DeviceInformation.FindAllAsync() method, which is async/await compatible, hence we simply use it like this

var devices = await DeviceInformation.FindAllAsync();

// output all devices
foreach (var device in devices)
{
   Debug.WriteLine(device.Name);
}

Obviously this is a little over the top if we’re looking for a specific device or set of devices. In such cases we can create an AQS query and pass this into one of the FindAllAsync overloads. Hence to recreate my previous post’s query looking for all Bluetooth devices we might prefer to use

var devices = await DeviceInformation.FindAllAsync(
    BluetoothDevice.GetDeviceSelectorFromPairingState(
        false));

Whilst this solution to the problem of locating devices may fulfil many of the developer’s requirements, an area it fails on is that once the developer has a list of devices they do not have a way to tell when devices are turned off/disabled/or otherwise no longer available. In such situations it’s better to watch for device changes.

Watching for device changes

The DeviceInformation.CreateWatcher method allows the developer to query for devices and via events, watch for items to be added, updated or removed. This would suit an RX type of implementation.

Here’s some code that demonstrates possible usage of the CreateWatcher

try
{
   deviceWatcher = DeviceInformation.CreateWatcher(
      BluetoothDevice.GetDeviceSelectorFromPairingState(false), 
      null,
      DeviceInformationKind.Device);

      deviceWatcher.Added += (watcher, args) =>
      {
         Debug.WriteLine($"Added {args.Name}");
      };
      deviceWatcher.Updated += (watcher, args) =>
      {
         Debug.WriteLine($"Updated {args.Id}");
      };
      deviceWatcher.Removed += (watcher, args) =>
      {
         Debug.WriteLine($"Removed {args.Id}");
      };
      deviceWatcher.EnumerationCompleted += (watcher, args) => 
      { 
         Debug.WriteLine("No more devices found"); 
      };
      deviceWatcher.Start();
}
catch (ArgumentException ex)
{
   Debug.WriteLine(ex.Message);
}

Again we’re using the AQS created via the GetDeviceSelectoryFromPairingState method and in this simplistic example, we simply subscribe to the Added/Updated/Removed and EnumerationCompleted events to output what devices have been added etc. We also need to be aware of possible ArgumentExceptions, such as incorrectly formatted GUID’s etc. See DeviceInformation Class for a more complete example of this usage.

Displaying the device picker in a UWP application

Developers can use the UWP device picker flyout control within their application to allow the user to select a device from a list of available devices. The list can be filtered to display only particular types of devices.

For example, here’s how to display the DevicePicker flyout without filtering, i.e. showing all available devices

var devicePicker = new DevicePicker();
devicePicker.Show(new Rect(x, y, width, height));

In this case we simply create a DevicePicker and call the Show method which is passed a rectangle where you want the picker to flyout from.

There’s an overload Show method which allows a placement as well.

If you run this code in your application you’ll find that devices are enumerated over and displayed as they are found, so obviously this may take a little bit of time to enumerate all devices.

In most cases we probably want to filter the DevicePicker for a certain type of device. For example if we want to locate all Bluetooth devices we would use the following

var devicePicker = new DevicePicker();

devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothLEDevice.GetDeviceSelectorFromPairingState(false));
devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothLEDevice.GetDeviceSelectorFromPairingState(true));
devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothDevice.GetDeviceSelectorFromPairingState(false));
devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothDevice.GetDeviceSelectorFromPairingState(true));

devicePicker.Show(new Rect(x, y, width, height));

In this case we’ve filtered the DevicePicker so it will only display BluetoothLE devices and Bluetooth devices both in a paired (the true parameter) or unpaired (the false parameter).

Obviously we’re going to want to get at the device information or the selected device, when using the Show method, we will need to subscribe to the DevicePicker’s DeviceSelected event, for example

devicePicker.DeviceSelected += (picker, args) =>
{
   // outputs the selected device name
   Debug.WriteLine(args.SelectedDevice.Name);
};

We can also respond to a couple of other events such as the DevicePickerDismissed and DisconnectButtonClicked.

As an alternate to the event approach, we could switch from using the Show method to use the async/await implementation which combines the Show and the DeviceSelected into he PickSingleDeviceAsync method, i.e.

var device = await 
   devicePicker.PickSingleDeviceAsync(
      new Rect(x, y, width, height));
// outputs the selected device name
Debug.WriteLine(device.Name);

UWP Application’s file restrictions and logging

UWP applications have restricted access to the local file system and this can cause a few issues when using logging frameworks if you’re expecting to write logs to c:\Temp
or %Temp% locations (for example).

Your UWP application can write to the application’s installation folder, for example

var installedLocation = 
   Windows.ApplicationModel.Package.Current.InstalledLocation.Path;

another alternatively is application data location, such as

var localFolder = 
   ApplicationData.Current.LocalFolder.Path;

// or

var localCache = 
   ApplicationData.Current.LocalCacheFolder.Path;

These last two location will translate to a location such as the following, where username is the (as you’d expect) username the user logged into the machine with, and the GUID is the package family name GUID (taken from the application’s manifest). This is actually an extended GUID.

C:\Users\<username>\AppData\Local\Packages\<guid>

Note: At the time of writing I’m not sure where the string after the underscore which follows the GUID comes from.

Let’s take a quick look at using Serilog’s File Sink to write our log files. Using NuGet install Serilog and Serilog.Sink.File and use the following code

Log.Logger = _logger = new LoggerConfiguration()
   .WriteTo.File(
      new JsonFormatter(renderMessage: true),
      ApplicationData.Current.LocalCacheFolder.Path + "\\log.txt", 
      rollingInterval: RollingInterval.Minute)
      .MinimumLevel.Verbose()
      .CreateLogger();

References

File access permissions

Adventures in UWP – Globalization & Localization

In a previous post I created a “default” UWP blank application, which did nothing. But we did look at some of the key parts of the template code, manifest etc.

Usually I would go the “Hello World” route and just display a TextBlock or similar to display the text “Hello World”, so let’s do that here and then look to make this post a little more useful by taking a look at globalization & localization.

Obviously if we were to actually deploy an application to the Window’s store it would be good to have it available in different languages etc.

I’m not intending to spend too long on this as it’s quite a large subject in and of itself, but let’s look at the basics.

In MainPage.xaml, add a TextBlock between the Grid (here’s the code including the Grid)

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   <TextBlock Text="Hello World" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center"/>
</Grid>

In the above code we’ve effectively hard coded “Hello World” into our application.

Globalization & Localization

Internationalization (also known as i18n) is the combination of Globalization & Localization.

Globalization tends to mean the implementation of code within your application which can change automatically based upon the locale, so for example formatting of numbers or dates.

Localization tends to mean the changes to an application for a different locale, such as translation etc.

Note: I covered some i18n coding for WPF previously in my post A quick look at WPF Localization Extensions.

Let’s localize our app.

Okay, we don’t have a lot of text to translate (or images or the likes), so this is very much an overview of the process we’d undertake on our application. Let’s change our “Hello World” into a format that can be localized.

To do this we use the x:Uid markup element on our TextBlock, for example

<TextBlock x:Uid="helloWorld" 
   HorizontalAlignment="Center" 
   VerticalAlignment="Center"/>

Note: In another post I intend to cover accessibility, such as the narrator. In some instances we might wish to add AutomationProperties.Name text to a control but we’ll also want that to be localized and so whilst a x:Uid=”hellWorld” might be used for a control, in the .resw file we’d have the name/key helloWorld.AutomationProperties.Name and put our localized text in here.

We don’t actually need to have the Text property, but you might find having something displayed at design time useful and so you can just as easily leave the Text=”Hello World” markup and it’ll be overwritten by our localization.

The x:Uid differs from the x:Name markup as it’s aimed specifically for localization.

Now we need to create our resources, in our project we simply create a folder (at the same level as our Assets) with the name of the locale we want to store resources for, so for example we can create en for general English language, or en-GB, en-CA, en-US for example, for British, Canadian and US variants of English.

See Supported Languages for a list of language codes.

With our folder in place we simple add a new item of type Resources file (.resw) and this gives us a simply grid entry screen for key/value pairs along with a comment for passing onto our translators (for example).

Within the grid, the key (actually it’s the header Name) is our x:Uid but in the format uid.PropertyName, where the property name for our TextBlock is Text. Therefore remember if the UI element changes from a TextBlock to a Button (for example) this PropertyName would need to also change from Text to Content.

We can (and should) also store string representations of colours, such as “Red” etc. as values for those elements where the colour may need to change for the different locale.

Testing our localization

So let’s assume we’ve created several folders and localized our application strings etc. How do we test the different localization without having to change our Windows setup.

There’s actually a Default language option in the app’s manifest, but changing this doesn’t appear to have the desire affect.

A simple way to change our locale is within the App constructor, simply place the following

ApplicationLanguages.PrimaryLanguageOverride = "fr-FR";

We could also have an option within the application for switching languages, in which case we’ve need to reload the UI, but I’m not going to cover that within this post.

Using the Multilingual App Toolkit

An alternate route to translation is using the MAT (Multiligual App Toolkit) which can be used in WPF or UWP.

The Multilingual app toolkit 4.0 for VS 2015 or Multilingual app toolkit for VS 2017. Give us another way to handle translations/localization.

MAT seems a little tricky to get working, but it’s not too bad once you know what’s required (ofcourse that statement can be used for most things).

  1. Select Tools | Multilingual App Toolkit and Enable Selection
  2. Depending upon your manifests Default Language (mine’s en-GB) you’ll need a folder of the same name, i.e. en-GB with a Resources.resw file in it before you can add translations via MAT. As the default language, the key’s and default strings will be taken from this file. So add our helloWorld.Text name and “Hello” as the value to this resource file.
  3. You should build the project here just to make sure all is working
  4. Now you can right mouse click on the project and select Multilingual App Toolkit and now Add translation languages will be enabled, from here you can select multiple languages.
  5. Let’s select fr-FR for some French translation. This will create another folder fr-FR, as you’d expect, along with a Resources.resw for this translation. Do not edit any new translation files, only the default language file
  6. Along with the Resource.rews a MultiligualResources folder will appears with xlf files matching the appname.language format, i.e. HelloWorld.fr-FR.xlf. It is the XLF file that we translate our text into.

Whilst we can edit our XLF in Visual Studio as it’s just an XML file, we can also double click on it from File Explorer to load via the Multilingual Editor. This editor could, ofcource, be used by a translator to go through each resource and supply the translation. Once saved MAT will again sync. but this time it will automatically supply the strings and identifiers to the fr-FR Resource.resw (in my case).

Each time we finished adding new strings to our default locale (in my case the en-GB Resource.resw) then rebuild to get MAT to resync. Then translate when you’re ready.

In most cases we’d wait until all (or most) of our application is in ready before sending the XLF to translators ofcourse, but for us to test things, just translate and rebuild to resync.

Pseudo language with MAT

Whilst the MAT includes many locales that you’ll recognise, it also includes a Pseudo language which is generated from your default language strings but with alterations to the string, for example taking “OK” and creating a longer string with semi-random characters as well as the O and K, so it’s still readable in English (my default language).

To get translations in the pseudo language, open the *.qps-ploc.xlf file and for each string you wish to translate click the Translate button or for all strings, click the Translate button’s drop down and select Translate All. This will then create translations for testing your layouts etc.

Using resource strings in the manifest, for the Display Name

In some cases we might wish to localize the Display name, i.e. Title of the main Window.

From the manifest we can reference our resource string using

ms-resource:myTitle

where myTitle is a key/name within the Resources.

We can (sort of) handle this in code by accessing using

ApplicationView.GetForCurrentView().Title = "My Title";

but actually this doesn’t replace the Display Name from the manifest but instead prepends the text.

Finally, using our resource in code

Whilst we obviously want to do most of our UI work in XAML, we still need to store strings etc. for use in code, for example when displaying a message box of the likes.

To use the resources in code we can declare the strings within the .resw. Interestingly, not sure if this is just me or how things work, but for strings that will be used in code, the name/key of the string does not include the .PropertyName format. Hence “hello.Text” fails to work when used in code, whereas “hello” as a key does work.

Here’s the code that we can use to get the string from the default resources

var rl = ResourceLoader.GetForCurrentView();
var r = rl.GetString("hello");
// r will now be our translated string

References

Globalization and localization
Put UI strings into resources

Monitoring your application using App Center

Microsoft’s App Center (https://appcenter.ms/apps) allows us to do several things, including build and distribution of our application(s), but what I’m interested in for this post, is the capabilities which allow us to monitor some usage information, tracing events and viewing exceptions.

Within App Center you need to create an application and tell App Center what OS and Platform is being used and it will respond by supplying you with information on how to “embed” App Center code into your application.

Once we’ve created an application in App Center we’ll be supplied with a key (currently you need a key per OS application).

Let’s now create a simply test application using Xamarin.Forms, although you can create a standard UWP application if you prefer.

Note: at this time WPF does not seem to be fully supported.

Creating our Xamarin.Forms application

  • In Visual Studio, select Mobile App (Xamarin.Forms) project, this will allow us to create a UWP, IOS and Android application (ensure all three platforms are selected).
  • Now add the two NuGet packages, Microsoft.AppCenter.Analytics and Microsoft.AppCenter.Crashes to each platform specific project.

Inside the shared project, edit the App.xaml.cs adding the following using clauses

using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;

and within the OnStart, add the following code

AppCenter.Start(
   "android=ANDROID_KEY;" +
   "uwp=UWP_KEY;" +
   "ios=IOS_KEY",
   typeof(Analytics), 
   typeof(Crashes));

For each platform you need to create a new application key within App Center. If you are only intending to create a single platform version of your application, for example a UWP application, you can use the following instead

AppCenter.Start(UWP_KEY,
   typeof(Analytics), 
   typeof(Crashes));

If we now run our application, App Center will start to log each time the application is run along with information regarding the OS being used, but what if we want to start to track certain usage, for example to find out if a feature is actually being used.

Exceptions and crash reporting

Crash/Exception reporting is enabled by default but obviously if you’re running inside the Debugger in Visual Studio, this may intercept such exceptions before they get sent to the App Center, so if your using a mobile device, you’ll need to actually deploy the application to test any exception handling.

However in instances where we want to both handle an exception (probably most cases) and log/track the exception we use code like the following

try
{
   // do something
}
catch(Exception e) 
{
   Crashes.TrackError(e);
}

We can also supply a dictionary with additional information to TrackError, for example

try
{
   // do something
}
catch(Exception e) 
{
   Crashes.TrackError(e, new Dictionary<string, string>
   {
      { "WithFile", filename }
   });
}

Tracking events

To track events, simple add the following line (obviously replacing the text with whatever you want to see in App Center when an event occurs).

Analytics.TrackEvent("New Feature Used");

we can also supply more information to the event tracking, by supplying a dictionary to the TrackEvent method, for example

Analytics.TrackEvent("New Feature Used", new Dictionary<string, string>
{
   { "WithFile", filename }
});

Turning Analytics on/off

Obviously you might want to have a configuration option which allows a user to opt-in/out of analytics, simply use

Analytics.SetEnabledAsync(false);

Offline behaviour

Obviously all this is great if the application/device in connected to the internet but in situations where the application or device are offline, messages will be stored locally. The FAQ states that up to 300 logs can be stored offline and once a internet connection is restored the messages will be sent to the App Center.

Using Lottie in your UWP apps.

Lottie is a library for displaying After Effects animations.

Let’s create a UWP application to try this out.

  • Create a UWP application
  • Add the LottieUWP package via NuGet

The easiest way to get something up and running is, head over to LottieFiles, find an animation and download it (you’ll be downloading a JSON file).

Place the JSON file into the Assets folder of your UWP solution and set the Build Action to Content.

Now, in the MainPage.xaml place the following code with the Grid

<lottieUwp:LottieAnimationView 
   FileName="Assets/success_animation.json" 
   AutoPlay="True" VerticalAlignment="Center" 
   HorizontalAlignment="Center" 
   RepeatCount="0" 
   Width="100" Height="100"/>

The namespace is

xmlns:lottieUwp="using:LottieUWP"

It’s as easy as that.

Adventures in UWP – Prism (more Unity than Prism)

Prism is a well used framework in WPF and it’s also available in UWP. So let’s try it out. We’re going to start by looking at switching the default generated (blank) UWP application into one which uses Prism or more specifically Unity and Prism’s navigation functionality.

  • Create a Blank UWP application
  • From Nuget install the package Prism.Unity (I’m using v6.3.0)
  • Edit App.xaml.cs and change the base class from Application to PrismUnityApplication (yes we’ll use Unity for this test), don’t forget to add using Prism.Unity.Windows;
  • Remove all generated code from App.xaml.cs except for the constructor
  • Open App.xaml and change it from using Application to PrismApplication, for example
    <windows:PrismUnityApplication
        x:Class="MathsTest.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MathsTest"
        xmlns:windows="using:Prism.Unity.Windows"
        RequestedTheme="Light">
    
    </windows:PrismUnityApplication>
    
  • Add the following bare bones method (yes it’s not handling possible startup states etc. as I wanted to reduce this code to the minimum)
    protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
    {
       NavigationService.Navigate("Main", null);
       return Task.FromResult(true);
    }
    
  • By default the UWP project will have created a MainPage.xaml but Prism’s navigation code expects this to be in a Views folder, so create a Views folder in your solution and move MainPage.xaml into this Views folder.

    If you see an exception along the lines of “The page name does not have an associated type in namespace, Parameter name: pageToken” then you’ve probably not got a view with the correct name within the Views folder. Don’t forget to update the XAML and the xaml.cs files to include Views in the name space, i.e. TestApp.Views.MainPage

At this point we have UWP running from Prism.

Adventures in UWP – Getting Started

For a while now I’ve wanted to do something in UWP (Universal Windows Platform).

UWP always gives me the “uncanny valley” sort of feeling; it looks like WPF and looks like a standard Windows .NET application, but it also has that feeling on the unknown about it. To illustrate what I mean, UWP application compile to an EXE, but anyone used to Windows programming will probably double click on the EXE and find that Windows responds with a message box stating “This application can only run in the context of an app container”.

We’ll cover this soon enough, but let’s start our adventure with the classic Hello World type example and look at the basic parts of a UWP application and using Visual Studio 2017 to run the application etc.

Versions etc.

First off, I’m using Windows 10.0.15063.0 and Visual Studio 2017, version 15.2 (26430.16). I state this upfront because I’ve found books/posts talking about previous versions telling us to expect this file and this dialog when creating a new project, so what you see may differ from what I describe here, depending upon your versions.

Creating our project

In Visual Studio, carry out the following

  1. File | New Project
  2. Visual C# | Windows Universal
  3. Select Blank App (Universal Windows)
  4. Name it HelloWorld
  5. You’ll be prompted to choose a target version and minimum version, leave these as defaulted for now

Navigating the project

Properties

Within the Properties section is the usual AssemblyInfo.cs, but also the Default.rd.xml. This is used to contain runtime directives (hence .rd.). This allows us to specify elements within our program that are available for reflection.

Reference

Unlike non-UWP applications, the References have only two items (excluding the Analyzers). Microsoft.NETCore.UniversalWindowsPlatform and Universal Windows.

Assets

By default the Assets folder contains seven png images. Including store logo and splash screen. These are templates (if you like) for your own images. Every one of the images is a square with a cross in it – so you’ll know pretty quickly if you’ve not supplied an image/logo/splash screen for some area.

App.xaml

Like WPF, we have an App.xaml (and ofcourse the App.xaml.cs code behind). The code behind has a fair bit more code within it, unlike WPF. Default code is there for us to handle state loading during the application launch, a point to save state when the application is suspended etc. Also, unlike WPF, the MainWindow (in this case MainPage) is navigated to via the OnLaunched code as opposed to being declared in the App.xaml file like WPF.

HelloWorld_TemporaryKey.pfx

A temporary key is created for us. As UWP is aimed at being downloaded and installed from the Windows Store (or side loaded) this requires the application to be signed, hence we’re given the starting point for this.

MainPage.xaml

MainPage.xaml and it’s code behind contain minimal XAML and code (like a standard WPF control). UWP tends to class these controls as Pages (reminds me of Silverlight).

Package.appxmanifest

Finally we come to the application manifest. This allows us to set up things like the application’s display name, the rotations supported (for tablet/phone type devices). We can assign our assets to specific scenarios, such as for tiles, app. icons and so on. We’ll also need to declare what capabilities the application needs access to. Sort of standard mobile phone development requirements, i.e. this application will require Bluetooth etc.

Note: It’s best to reduce the capabilities to the bare minimum required as some user’s may prefer to lock down the access an application has.

What happens if we run the application now?

So if we want to run the application, you’ll notice that (at least on my install of Visual Studio) there the run button on the toolbar with Local Machine shown (mine’s also defaulted to x86 instruction set). From the drop down we also have Simulator, Remote Machine, Device as well as a bunch of Mobile Emulators of different screen sizes.

The emulators obviously allow us to view our application on a mobile phone or tablet like sized device.

Remote Machine allows us to run the application remotely, so for example on a Windows tablet, but without needing to install it directly etc.

The simulator is a virtual device or maybe better thought of as a remote desktop. The odd thing is that you’re really remote desktop-ing into your own machine, so changes to the simulator affect your machine.

So, let’s choose Local Machine, then we’re doing the equivalent of running a “standard” windows application. You’ll notice a square with a cross in it displayed, this is the SplashScreen.scale-200.png supplied by the project template within our Assets folder. Change this and then re-run to confirm.

Once running our application is, as expected, a blank application, but before we move onto actually writing some code/designing the UI, when we ran the application Visual Studio actually installed the application for us in the Start Menu, under Recently Added you should see HelloWorld (if you followed my naming for the application). If you attempt the run the EXE within the build folder, you’ll get the message box stating “This application can only run in the context of an app container”, however from the Start Menu, the application will be correctly run from a container.

Finally for this section, when you run the application via Visual Studio you’ll see four icons on your main page, these include tools to view the visual tree of a selected item at runtime and enable selected option, display layout adorners and a track focused element tool.

These, by default, are hidden outside of the debugger, but we can also hide within the debugger experience by selecting Tools | Options | Debugging | General, then locate Enable UI Debugging Tools for XAML and deselect this option.

The splash screen

As mentioned previously, we define the splash screen image (or edit the existing) within the Assets, as this is assigned via the manifest. UWP automatically displays the splash screen for us over the application Window and within App.xaml.cs, the OnLaunched method, when Window.Current.Activate() is called, the splash screen will be removed (obviously it will not immediately happen as the Windows message will need to be sent through, but it’s at this point the UWP application then “properly” starts your application. Hence within OnLaunched, is the place to restore state or setup anything prior to the splash screen being removed.

Note: Like Windows Services, your application is expected to start within a certain amount of time or it’s perceived as failing to start. I’ve read this time is approximately 15 seconds. So you’ll need to be a little more creative if loading your application takes longer than this, i.e. run code on a non-blocking thread or simply lazy load state etc.

Where’s the Windows 10 mobile emulator?

So I’ve been working on some ideas on cross platform .NET development using Visual Studio 2015 and Xamarin. I have the Windows UWP application working fine on Windows 10 but wanted to see how it would look on Windows 10 phone – surprisingly I found the Windows 10 phone emulator didn’t exist as part of the Visual Studio installation (possibly I missed a check box when install or the likes) but it’s easy enough to get.

Just go to Downloads and tools for Windows 10 in the Other download options section there’s a Download the emulator link. From here we can download and install the Windows 10 mobile emulator.

Take a look as Test with the Microsoft Emulator for Windows 10 Mobile Test with the Microsoft Emulator for Windows 10 Mobile also which gives some useful information on using the emulator in different scenarios/configurations.