#UWPXAML – Compiled Binding – Binding to events

Coming with Windows 10 are a lot of new features especially for XAML when creating a Universal Windows Platform application aka. UWP app. We can mention a few of them: new controls (as the RelativePanel, the SplitView and more); new tools for building responsive and adaptive UI (AdaptiveTrigger, Extension SDKs, etc.); and a new way to bind data to the UI, Compiled Binding.

This series on Compiled Binding will be composed of several parts:

 

{x:Bind} and events

As we’ve seen in the previous part « Part 1: Binding to data« , x:Bind is great when you want to bind various source of data to your UI. It does mostly the same things as classic binding but with better performance and compile-time checks.

x:Bind doesn’t stop here. It goes a step further than its cousin: it can also bind event handlers to events, regardless if it has been thought by the control’s author unlike {Binding}, which needs ICommand support to be built into the control.

All that in a natural way thanks to code generation introduced by compiled binding.
 

Before {x:Bind}

Before compiled binding, you had three ways to handle events in XAML.

1st Way: Register an event handler defined in your code behind directly to your control’s event in XAML. That’s the most common way of doing it as it’s how the XAML framework has been built.

<Button Click="CodeBehind_ButtonClicked" />

 

2nd Way: Use Command properties when available in conjunction with ICommand. This allows you to define your event handler outside the code-behind class, like in your ViewModel.

public class ViewModel
{
    private ICommand _clickCommand;
    public ICommand ClickCommand
    {
        get { return (_clickCommand ?? _clickCommand = new RelayCommand<object>(this.OnButtonClicked)); }
    }

    private void OnButtonClicked(object parameter) { ... }
}

Then in your XAML file, you just have to bind to it.

<Button Command="{Binding ClickCommand}" CommandParameter="HelloWorld" />

One limitation: the control must have built-in support for it. And well, apart from Button and its Command property, barely any other control have such thing.

For example, if you want to handle SelectionChanged of ListView, there isn’t any property allowing you to react to SelectionChanged event from your ViewModel without using the first way we saw.
 

3rd Way: Use Behavior to bind ICommand to any event.

<ListView>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <command:EventToCommand Command="{Binding SelectionChangedCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListView>

To get around the previous limitation, Blend added an Interactions SDK that allows you, among other things, to create custom behaviors. These behaviors can be attached to controls, that way you can extend on the control’s behavior without having to create another control that inherits from the former.

You can create a behavior that subscribes to whatever event you need and let it call your ICommand, just like the Command property of Button does.

Behaviors with this purpose already exist in MVVM libraries such as EventToCommand from the well-known MVVMLight.
 

{x:Bind}, the Event Handler

Now in UWP apps, you have another way to do so: {x:Bind}.

Let’s say you have a ViewModel and you want to handle the SelectionChanged event of a ListView in a method named OnSelectionChanged, that is in your ViewModel.

public class MyPageViewModel
{
    public ObservableCollection<Book> Books { get; set; }

    public void OnSelectionChanged(object sender, SelectionChangedEventArgs args) { ... }
}

With {x:Bind}, all you have to do is just bind OnSelectionChanged of your ViewModel to the event you want to handle.

<ListView ItemsSource="{x:Bind ViewModel.Books}" SelectionChanged="{x:Bind ViewModel.OnSelectionChanged}" />

There, you just bound yourself an event! It’s that easy.

As you can see, to hook up an event to a method, you just need to use the same markup extension like you would with data binding. Behind, the compiler will add the required logic to call your method when the event is raised.

But when doing so, the compiler expects that the method you try to bind is public and respects one of these conditions:

  • Have the exact event signature
  • Have the same event signature, but parameters can be of a more generic type (up to object)
  • Have no parameter at all

Let’s take a look at how to meet these conditions when binding to the Click event of a button.

XAML

<Button Click="{x:Bind OnButtonClicked}" />

C#

// Exact event signature
public void OnButtonClicked(object sender, RoutedEventArgs args) { … }

// Same event signature, args' type is more generic (RoutedEventArgs --> EventArgs)
public void OnButtonClicked(object sender, EventArgs args) { … }

// Same event signature, args' type is now object
public void OnButtonClicked(object sender, object args) { … }

// No parameter
public void OnButtonClicked() { … }

Asynchronous methods are also supported, just set the « async » keyword on your method signature.

// Asynchronous event handler
public async void OnButtonClicked() { … }

Where can I put those methods, you may ask.

Well, you can put them in your code-behind class (this is x:Bind’s root context, remember?) or you can put them in your ViewModel! No need for ICommand nor EventToCommand behavior now. It just got a whole lot easier compared to what we were used to with classic binding, while using MVVM.

<!-- OnButtonClicked declared in code-behind (except when used in DataTemplate) -->
<Button Click="{x:Bind OnButtonClicked}" />

<!-- OnButtonClicked declared in the ViewModel -->
<Button Click="{x:Bind ViewModel.OnButtonClicked}" />

<!-- OnButtonClicked declared on a data model exposed by the ViewModel -->
<Button Click="{x:Bind ViewModel.LastReadBook.OnButtonClicked}" />

 

Moving on to the last part

We’ve seen pretty much everything x:Bind can offer, or have we?
There is one last neat feature that x:Bind brings: Incremental rendering in list controls.
To learn more about this, head to « Part 3: Incremental rendering with x:Phase« .

#UWPXAML – Compiled Binding – Binding to data

Coming with Windows 10 are a lot of new features especially for XAML when creating a Universal Windows Platform application aka. UWP app. We can mention a few of them: new controls (as the RelativePanel, the SplitView and more); new tools for building responsive and adaptive UI (AdaptiveTrigger, Extension SDKs, etc.); and a new way to bind data to the UI, Compiled Binding.

This series on Compiled Binding will be composed of several parts:

 

Databinding with {x:Bind}

Now that you know what compiled binding is and in what it differs from classic binding, let’s see how to use it in different conditions. If you don’t, see « Part 0: Compiled Binding, what is it? »
 

{x:Bind} over a simple value

To start this series of compiled binding examples, we will see how to bind to a single scalar property.

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public string ApplicationTitle = "UWP Series - Compiled Binding";

    public MainPage()
    {
        this.InitializeComponent();
    }
}

Remember that I said x:Bind’s root context is the instance of control which we are currently declaring in its XAML file?

To bind to a value, we need to define it in the « .xaml.cs » file of the control with the public accessor as x:Bind doesn’t have access to protected/private fields. We don’t set the DataContext property because it’s not the root context of compiled binding.

This is also useful to avoid DataContext with compiled binding as it is of type Object and if you need to access some sub-properties of the type you put in DataContext, x:Bind will require that you define the real type in your path like this « {x:Bind Path=DataContext.(local:User.FirstName)}« , reducing the readability of your XAML.

So here, we define the ApplicationTitle string as a public field, but we can also declare it as a property.

Now that we have access to it with x:Bind in XAML, let’s see how to bind to it.

MainPage.xaml

<Page x:Class="UWPSeries.CompiledBinding.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Margin="8" Text="{x:Bind ApplicationTitle}" />
    </Grid>

</Page>

As you can see, it is the same as classic binding, we just have replaced the keyword Binding (also known as Markup Extension) by x:Bind and it works!

Compiled Binding
 

{x:Bind} versus the world

From now on, every code samples will use this Book class.

Book.cs

public class Book
{
    public string ImageUrl { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
}

 

{x:Bind} over a ViewModel

Using x:Bind with a ViewModel is the same as a scalar data, you can define your ViewModel as a public field/property in your « .xaml.cs » file, and then x:Bind will have access to it in the XAML file.

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public Book LastReadBook = new Book
    {
        ImageUrl = "ms-appx:///Images/H2G2_UK_front_cover.jpg",
        Title = "The Hitchhiker's Guide to the Galaxy",
        Author = "Douglas Adams"
    };

    public MainPage()
    {
        this.InitializeComponent();
    }
}

MainPage.xaml

<Image Source="{x:Bind LastReadBook.ImageUrl}" />
<TextBlock Grid.Column="1" VerticalAlignment="Center">
    <Run Text="{x:Bind LastReadBook.Title}" />
    <LineBreak />
    <Run Text="{x:Bind LastReadBook.Author}" />
</TextBlock>

As you can see, we specify in the binding path the name of the public field we declared in the « .xaml.cs » file followed by a point to access its properties.

Compiled Binding
 

{x:Bind} in a DataTemplate

To use x:Bind in a DataTemplate, there is only one mandatory step. You need to declare to the DataTemplate what will be the type of the context to render. This is done by setting the attribute « x:DataType » on the DataTemplate to the name of the type you will use.

<DataTemplate x:DataType="local:Book">
    <Grid Height="150">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Image Source="{x:Bind ImageUrl}" />
        <TextBlock Grid.Column="1" VerticalAlignment="Center">
            <Run Text="{x:Bind Title}" />
            <LineBreak />
            <Run Text="{x:Bind Author}" />
        </TextBlock>
    </Grid>
</DataTemplate>

One thing: in DataTemplate, the root context of compiled binding is the current item you are trying to render just like with classic binding. So here, when using « {x:Bind Title} », you bind to the current item’s title.

Compiled Binding
 

Special case : {x:Bind} in a ResourceDictionary

When you are creating a DataTemplate, you may want to put it in a separate ResourceDictionary to allow the reuse of this DataTemplate.

But when doing so with compiled binding, you get a build error stating « This Xaml file must have a code-behind class to use {x:Bind}. »

As I said in the previous part, compiled binding is achieved by doing code generation in the « .xaml.g.cs » file linked to your « .xaml » file where you are using x:Bind. But when putting a DataTemplate with compiled binding in a ResourceDictionary, as the dictionary doesn’t have a « .xaml.cs » file, also called a code-behind class, the compiler can’t associate the file generated to your resource dictionary.

To resolve this, you need to create that missing file, to create a partial class that inherits from ResourceDictionary and declare this class with « x:Class » in your ResourceDictionary’s XAML.

DataTemplateResourceDictionary.xaml.cs

public partial class DataTemplateResourceDictionary : ResourceDictionary
{
    public DataTemplateResourceDictionary()
    {
        this.InitializeComponent();
    }
}

DataTemplateResourceDictionary.xaml

<ResourceDictionary
    x:Class="UWPSeries.CompiledBinding.DataTemplateResourceDictionary"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPSeries.CompiledBinding">

    <DataTemplate x:DataType="local:Book" x:Key="BookDataTemplate">
        <Grid Height="150">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>

            <Image Source="{x:Bind ImageUrl}" />
            <TextBlock Grid.Column="1" VerticalAlignment="Center">
                <Run Text="{x:Bind Title}" />
                <LineBreak />
                <Run Text="{x:Bind Author}" />
            </TextBlock>
        </Grid>
    </DataTemplate>

</ResourceDictionary>

Tip: To simplify this step, you can use the file template « Blank Page » of Visual Studio like you would to create a new page, but once the appropriate files created (« .xaml » and « .xaml.cs »), you change the Page tags to ResourceDictionary tags. All will be set up correctly allowing you to use x:Bind.

Last step is to reference your ResourceDictionary to be used by your application.

As we have created a class to hold the generated binding logic, we can’t use the classic way of declaring ResourceDictionary:

App.xaml

<Application x:Class="UWPSeries.CompiledBinding.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="using:UWPSeries.CompiledBinding"
             RequestedTheme="Light">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="DataTemplateResourceDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

Instead, we declare it by instantiating it directly.

App.xaml

<Application
    x:Class="UWPSeries.CompiledBinding.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPSeries.CompiledBinding"
    RequestedTheme="Light">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <local:DataTemplateResourceDictionary />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

 

{x:Bind} over another control

x:Bind also has the capability to bind to another control inside the page/usercontrol you are working on, like ElementName and RelativeSource from classic binding.

This is easily done because as we saw in « {x:Bind} over a simple value« , {x:Bind} has access to the page instance. Setting a name to a control make it available in the page’s code-behind in a field of the same name. x:Bind can then use this named control in its path to bind to a property of it.

MainPage.xaml

<TextBox x:Name="InputTextBox" Text="I'm binded" />
<TextBlock Margin="8" Text="{x:Bind InputTextBox.Text, Mode=OneWay}" />

I set the binding as OneWay because x:Bind is by default OneTime and thus not updating when the user starts typing in the textbox.

Compiled Binding
 

Going further

MSDN
« Data binding in depth »
https://msdn.microsoft.com/en-us/library/windows/apps/mt210946.aspx

Channel 9
« Improvements to XAML data binding »
https://channel9.msdn.com/Events/Windows/Developers-Guide-to-Windows-10-RTM/Improvements-to-XAML-data-binding

Build 2015
« Data Binding: Boost Your Apps’ Performance Through New Enhancements to XAML Data Binding » https://channel9.msdn.com/Events/Build/2015/3-635
 

Next time on Compiled Binding: binding to events

Data binding with x:Bind is great like we’ve just seen, but what about event binding?
Head to « Part 2: Binding to events » to learn about how to use compiled binding with events.

#UWPXAML – Compiled Binding – What is it?

Coming with Windows 10 are a lot of new features especially for XAML when creating a Universal Windows Platform application aka. UWP app. We can mention a few of them: new controls (as the RelativePanel, the SplitView and more); new tools for building responsive and adaptive UI (AdaptiveTrigger, Extension SDKs, etc.); and a new way to bind data to the UI, Compiled Binding.

This series on Compiled Binding will be composed of several parts:

 

A quick refresh on Classic Binding

Before going into details about Compiled Binding, let’s get a refresh on “classic” binding.

If you ever have developed a XAML app (with WPF, Silverlight, Windows Phone or Windows 8 Store App), you’ll be most likely familiar with classic data binding.

It uses the {Binding} syntax to pass, observe and update an underlying data to the view easily, therefore simplifying separation of concerns: the view doesn’t have to know about the data, retrieve and update logic being handled by a binding source object created by {Binding} thus making it best used with the MVVM pattern.

Here’s a code sample using classic binding:

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        this.DataContext = new Person() { LastName = "Doe", FirstName = "John" };
    }
}

MainPage.xaml

<StackPanel>
    <TextBlock Text="{Binding LastName}" />
    <TextBlock Text="{Binding FirstName}" />
</StackPanel>

FirstName and LastName here are called paths, they will be resolved at runtime, requiring a small overhead due to the use of reflection.
 

Introducing Compiled Binding

What is Compiled Binding?

Introduced with Windows 10, Compiled Binding is very similar to Classic Binding as it serves the same purpose but with some slight differences.

Compiled Binding is used with the {x:Bind} syntax as opposed to the {Binding} syntax of Classic Binding. It still uses the notifying interfaces (like INotifyPropertyChanged) to watch for changes but {x:Bind} is by default OneTime compared to {Binding} which is OneWay.

The reason for that is that most of the time, you just want to display a value on screen and don’t need it to change over the lifetime of your page. Setting binding to be OneTime by default, remove the need to watch for changes and thus reduce CPU and memory usage.

You can still use OneWay and TwoWay binding, you just need to set it like you normally would with classic binding:

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public Person Person = new Person() { LastName = "Doe", FirstName = "John" };

    public MainPage()
    {
        this.InitializeComponent();
    }
}

MainPage.xaml

<TextBlock Text="{x:Bind Person.LastName, Mode=OneWay}" />
<TextBox Text="{x:Bind Person.FirstName, Mode=TwoWay}" />

The main difference, as the name implies, is that the binding is actually « compiled », the paths are resolved at compile-time rather than runtime like classic binding, this permits to have a better troubleshooting experience (mistyped or invalid paths are treated as build error instead of just outputting an error message in the console) and remove the overhead due to reflection usage, which are both great.

This compilation is achieved by code generation. When you use {x:Bind} instead of {Binding}, the compiler will add logic into the « .xaml.g.cs » file corresponding to your « .xaml » file.

Data binding with {x:Bind} has another feature that {Binding} doesn’t have: incremental rendering of the items in ListViewBase-derived controls like ListView and GridView. This is done by using both {x:Bind} and the attribute x:Phase on controls inside your DataTemplate.

<DataTemplate x:DataType="local:Person">
    <StackPanel>
        <TextBlock Text="{x:Bind LastName}" />
        <TextBlock Text="{x:Bind FirstName}" x:Phase="1" />
    </StackPanel>
</DataTemplate>

Based on the ContainerContentChanging event that came with Windows 8.1, x:Phase allows you to progressively render your DataTemplate inside long list of data while the user is scrolling fast.

As you can see in the example, just set the x:Phase attribute on an x:Bind databound element and its rendering will be delayed until the CPU will have more time for it. If no phase is set, it’s by default phase 0, so whenever the item can be rendered, the element will also be.

That way, you have control on what to display first instead of just showing a placeholder. Used effectively, this can greatly enhanced your app’s user experience.

And finally, {x:Bind} is also capable to bind event handlers to events.

With classic binding, this was only possible by using ICommand to bind ViewModel’s methods to a Button click. If you wanted to bind to an event with no corresponding built-in Command property, you had to use a behavior and Interactions library from Blend SDK, usually you had to use EventToCommand behavior from MVVM libraries like MVVMLight.

One important thing to note also is that while classic binding uses the property DataContext as a root source for evaluating binded paths, Compiled Binding on the other hand directly references the root control in which it is used. For example, when using compiled binding in a page like MainPage, {x:Bind HelloWorld} will reference MainPage.HelloWorld. A field, a property or a method named HelloWorld must exist on MainPage and must be public. This also works when using compiled binding in a UserControl.

We’ll see in the next section a more complete comparison between {x:Bind} and {Binding}.

NB: Compiled Binding is only available for Windows 10 Universal apps (UWP). There is actually no plan to port it to WPF or Windows 8 apps in the future.

 

{Binding} versus {x:Bind}

Here’s a non-exhaustive list of differences between classic binding and compiled binding:

Classic Binding Compiled Binding
Creation Runtime Compile-time
Syntax {Binding LastName} {x:Bind LastName}
Root path context DataContext Root control (Page, UserControl, etc.)
Default mode OneWay OneTime
Invalid path Silently output an error in the console at runtime Build error
INotifyPropertyChanged
INotifyCollectionChanged
Supported Supported
Converters Supported Supported
Duck typing Supported Not supported
Dynamic creation (in code behind) Supported Not supported

Compiled Binding is missing some features from classic binding like Source, UpdateSourceTrigger, TemplatedParent, etc. If you really need these features, you should stick with classic binding when necessary.

RelativeSource=Self is a special case, the keyword itself is missing in compiled bindings but you just need to rewrite your binding because {x:Bind} has access to the root control instance and so has access to every named control in that root control.

RelativeSource with classic binding:

<TextBlock x:Name="TestClassicBinding" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" />

RelativeSource with compiled binding:

<TextBlock x:Name="TestCompiledBinding" Text="{x:Bind TestCompiledBinding.Name}" />

For a more complex use like binding to an unknown ancestor, stick with classic binding and RelativeSource.
 

Can I use both Compiled Binding and Classic Binding in a single project?

Of course you can!

As I said earlier, {x:Bind} only notifies the compiler to add some logic to handle passing a data to the UI that does not need usage of reflection at runtime like {Binding}.

Classic Binding is still available for UWP apps and is sometimes needed to achieve something Compiled Binding does not support such as Duck Typing, where you just know the property names but don’t know about the source object’s type (example : Property « Age » of classes Person and Wine).

It’s welcome when porting existing Windows 8 apps to Windows 10.

You can even use both bindings on a single control:

<TextBlock Text="{x:Bind Person.LastName}" Foreground="{Binding LastNameForegroundColor}" />

But Compiled Binding is currently only available for Universal Windows Platform projects.
 

When should I use Compiled Binding over Classic Binding?

Well, mostly anytime you can.

It really is a great way to enhance your app’s performance and simplify it a little (ICommand no more necessary) while remaining as easy to use as classic binding and as a bonus, troubleshooting becomes easier thanks to compile-time check of your paths!

Classic Binding is still there for you to use. It’s useful when you’re porting a previous Windows 8 app to Windows 10, or when you need advanced features only achievable without knowing the binded type at compile-time (for example, when you are dynamically loading XAML in your app or when your DataTemplate can be used with multiple types not having necessarily a common ancestor)
 

Binding to data

That’s all for introduction on compiled binding.
Head to « Part 1: Binding to data » to learn about how to use compiled binding with data.

Hey Cortana, do you speak JavaScript?

In this article I will try to describe every steps to use Cortana with your JavaScript UWP app.

The first step is to create an xml file that represents the Voice Command Definition :

<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
  <CommandSet xml:lang="fr-fr" Name="VDM_fr-fr">
    <CommandPrefix> VDM, </CommandPrefix>
    <Example> Affiche les dernières VDM </Example>
    
    <Command Name="showlast">
      <Example> Affiche les dernières VDM </Example>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> Affiche [les] dernières </ListenFor>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> Affiche [mes] dernières </ListenFor>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> Ouvre [les] dernières </ListenFor>
      <ListenFor RequireAppName="BeforeOrAfterPhrase"> montre [moi] [les] dernières </ListenFor>
      <Feedback> affichage des dernières VDM </Feedback>
      <Navigate />
    </Command>
    <Command Name="showcategorie">
      <Example> Affiche les VDM de travail</Example>
      <ListenFor RequireAppName="ExplicitlySpecified"> ouvre les {builtin:AppName} [de] {cat}</ListenFor>
      <ListenFor RequireAppName="ExplicitlySpecified"> affiche les {builtin:AppName} [de] {cat}</ListenFor>
      <Feedback> ouverture des VDM de {cat}</Feedback>
      <Navigate />
    </Command>

    <PhraseList Label="cat">
    </PhraseList>
  </CommandSet>
  <CommandSet xml:lang="en-us" Name="VDM_en-us">
    <CommandPrefix> FML </CommandPrefix>
    <Example> Show me the latest </Example>

    <Command Name="showlast">
      <Example> Show me the latest </Example>
      <ListenFor RequireAppName="AfterPhrase"> show [me] the latest </ListenFor>
      <ListenFor RequireAppName="AfterPhrase"> open the latest </ListenFor>
      <ListenFor RequireAppName="AfterPhrase"> display the latest </ListenFor>
      <Feedback>  display of the last FML</Feedback>
      <Navigate />
    </Command>

    <Command Name="showcategorie">
      <Example> Displays the FML of love </Example>
      <ListenFor RequireAppName="ExplicitlySpecified"> Opens the  {builtin:AppName} [of] {cat}</ListenFor>
      <ListenFor RequireAppName="ExplicitlySpecified"> Displays the {builtin:AppName} [of] {cat}</ListenFor>
      <Feedback> opening FML of {cat}</Feedback>
      <Navigate />
    </Command>

    <PhraseList Label="cat">
    </PhraseList>
  </CommandSet>

</VoiceCommands>
  • In this file the root element is the VoiceCommands Element, it’s contains a list of commandSet elements. Each commandSet is for a language.
    • An commandSet contains a list of command (and others things …)
      • A command is a “command” and contains an example, and multiple elements of ListenFor, a feedback element, and an instruction element (navigate in the first sample) that explicitly specifies that this command will navigate to your app.
        • ListenFor is the command phrase, it has a RequireAppName attribute that specifies where the app name can appear in the voice command.
      • A PhraseList that contains multiple item, each Item specifies a word or phrase that can be recognized to initiate the command that references the PhraseList (optional). You can optionnaly load dynamically a list of items from your code.

You have to be very careful, when you write this file! If you don’t respect the structure or If you miss an element, the Cortana API will fall in error without any information*.

The final step.
Instantiate your new XML file of VCD, in your JavaScript code.

In this following code, I call initCortana function to initialize the VCD file using de VoiceCommandDefinitionManager API located in the Windows.ApplicationModel.VoiceCommands namespace.

You have to pass your xml file to the « installCommandDefinitionsFromStorageFileAsync » function. If everything it’s not OK the callback of the promise returns a error and you pass by:

console.error(‘error file vdmvoicecommands.xml’, er);

In this case: check and re check an re re re check your VCD file 🙂

If the file was initialized correctly, you could add a list of items to populate the phrase lists.



    var wap = Windows.ApplicationModel.Package;
    var voiceCommandManager = Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager;

    var initCortana = function (categories) {
        categories = categories || [];
        return wap.current.installedLocation.getFileAsync("vdmvoicecommands.xml").then(function (file) {
            return voiceCommandManager.installCommandDefinitionsFromStorageFileAsync(file);
        }, function (er) {
            console.error('error file vdmvoicecommands.xml', er);
        }).then(function () {
           var language = window.navigator.userLanguage || window.navigator.language;

            var commandSetName = "VDM_" + language.toLowerCase();
            var commansets = Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.installedCommandDefinitions;
            if (commansets.hasKey(commandSetName)) {
                var vcd = commansets.lookup(commandSetName);
                var phraseList = [];
                categories.forEach(function (c) {
                    phraseList.push(c.title);
                });
                return vcd.setPhraseListAsync("cat", phraseList).then(function () {
                    console.log("VCD loaded !");
                 }, function (er) {
                    console.error('error set phraseList', er);
                })
            } else {
                console.warning("VCD not installed yet?");
            }
        }, function (ee) {
            console.error("installCommandDefinitionsFromStorageFileAsync error", ee);
        });
    }

Now you have to handle the activation event that will get sent to your app, and parse arguments.

  app.addEventListener("activated", function (args) {
        var appLaunchVoiceCommand = activation.ActivationKind.voiceCommand || 16;
        if (args.detail.kind === appLaunchVoiceCommand) {
            return handleVoiceCommand(args);
        }
    });

The handleVoiceCommand function parse the args passed from the activated app event and do the navigation to the right place

    var app = WinJS.Application;
    var commands = {
        "showlast": function (commandresult) {
            return WinJS.Navigation.navigate(VDM.Pages.VDMList, { viewType: 'last', viewLabel: WinJS.Resources.getString('appbar_views_last') });
        },
        "showcategorie": function (commandresult) {
            var categorie = commandresult.semanticInterpretation.properties.cat[0];
            return WinJS.Navigation.navigate(VDM.Pages.VDMList, { viewType: categorie.toLowerCase(), viewLabel: categorie });
        }
    }
    var handleVoiceCommand = function(args) {
        if (args.detail && args.detail.detail) {
            var voicecommand = args.detail.detail[0];
            if (voicecommand) {
                var result = voicecommand.result;

                if (result) {
                    var commandname = result.rulePath ? result.rulePath[0] : '';
                    var properties = result.semanticInterpretation ? result.semanticInterpretation.properties : {};
                    console.log("voice activation (" + commandname + ") confidence: " + result.rawConfidence, result);
                    var cmd = commands[commandname];
                    if (cmd) {
                        return cmd(result).then(function () {
                            VDM.Utils.loadMainAds();
                        });
                    }
                }

            }
        }
    }
    app.addEventListener("activated", function (args) {
        var appLaunchVoiceCommand = activation.ActivationKind.voiceCommand || 16;
        if (args.detail.kind === appLaunchVoiceCommand) {
            return handleVoiceCommand(args);
        }
    });

Let’s talk more with the app (with appService)

If you need a deeper integration with Cortana, you could also « talk » with her using an app service.

An app service is a Background task that Cortana could call when you use a command. You will have to explicitely declare which service Cortana must call in your command file.

    <Command Name="getFML">
      <Example> tell me a FML </Example>
      <ListenFor RequireAppName="ExplicitlySpecified"> tell me a {builtin:AppName} </ListenFor>
      <Feedback> Here an FML </Feedback>
      <VoiceCommandService Target="FMLVoiceCommandService"/>
    </Command>

Now let’s implement the Application Service. You must add it to your application manifest by pointing to JavaScript file, and give it the name you use in the command file :

 <uap:Extension Category="windows.personalAssistantLaunch"/>
 <uap:Extension Category="windows.appService" StartPage="js/voiceCommandService.js">
    <uap:AppService Name="FMLVoiceCommandService"/>
 </uap:Extension>

Beware the visual studio appxmanifest editor, it removes this entry if anything changes in it (like a upgrade of version when you generate a new appx package) this bug will certainly be corrected in the update 1 of Visual Studio.

Now let’s create the javascript file and implement the service itself.

When you are using JavaScript App Services are a lot like independant web workers. You can import all the JS file you need to run your code by using importScripts

importScripts("/WinJS/js/base.js");
importScripts("/js/FML.API.js");

The service is loaded by cortana, so when is loaded the doWork function is called.
If the Windows.UI.WebUI.WebUIBackgroundTaskInstance.current.triggerDetails is an instance of Windows.ApplicationModel.AppService.AppServiceTriggerDetails, we can get voice command used to launch this task and do things like:

  • Send an waiting response message
  • displays items
  • Send a final response message
var appService = Windows.ApplicationModel.AppService;
var backgroundTaskInstance = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;
var details = backgroundTaskInstance.triggerDetails;
var deferral = backgroundTaskInstance.getDeferral();

if (details instanceof appService.AppServiceTriggerDetails) {
    voiceServiceConnection = voiceCommands.VoiceCommandServiceConnection.fromAppServiceTriggerDetails(details);
    voiceServiceConnection.addEventListener("voiceCommandCompleted", onVoiceCommandCompleted);

    voiceServiceConnection.getVoiceCommandAsync().then(function completed(voiceCommand) {

    // here you can check the voiceCommand, call an API (or read a file) and send messages to Cortana UI

            var userMessage = new voiceCommands.VoiceCommandUserMessage();
                    userMessage.spokenMessage = "I'm Cortana and I read this awesome message";
                    userMessage.displayMessage = "I'm Cortana and I read this awesome message";
            var response = voiceCommands.VoiceCommandResponse.createResponse(userMessage);
            return voiceServiceConnection.reportSuccessAsync(response);

    });
}

The displayMessage string must not exceed 256 character

And now, with this, you can ask Cortana: « hey cortana, tell me a FML »

Bouton précédent (Back Button) avec le System Navigation Manager dans les applications (UWP) Windows 10

Dans les nouvelles applications Windows 10, nous avons la possibilité dans la version desktop d’une application d’utiliser le bouton de navigation (bouton précédent) du système qui est placé à coté du nom de l’application dans la barre de titre (comme celui qu’on trouve dans l’application de paramètres:

back

Ce bouton est nativement géré par WinJSContrib, il suffit pour cela d’activer l’option « enableSystemBackButton » :

 WinJSContrib.UI.enableSystemBackButton = true;

Un sample est disponible ici 🙂

Vous pouvez aussi l’implémenter manuellement. Il suffit d’utiliser la classe SystemNavigationManager et de modifier la propriété appViewBackButtonVisibility pour afficher ou cacher le bouton.

// il faut vérifier la disponibilité de l'api (disponible que sur desktop)
if (window.Windows && window.Windows.UI && Windows.UI.Core && Windows.UI.Core.SystemNavigationManager) {
    Windows.UI.Core.SystemNavigationManager.getForCurrentView().appViewBackButtonVisibility = Windows.UI.Core.AppViewBackButtonVisibility.visible;
    // ou pour cacher le bouton
    Windows.UI.Core.SystemNavigationManager.getForCurrentView().appViewBackButtonVisibility = Windows.UI.Core.AppViewBackButtonVisibility.collapsed;
}

Et pour gérer le clique il suffit de se brancher sur l’événement onbackrequested:

if (window.Windows && window.Windows.UI && Windows.UI.Core && Windows.UI.Core.SystemNavigationManager) {
    var systemNavigationManager = Windows.UI.Core.SystemNavigationManager.getForCurrentView();
    systemNavigationManager.onbackrequested = function (args) {
        if (WinJS.Navigation.canGoBack) {
            WinJS.Navigation.back();
            args.handled = true;
        } else {
            systemNavigationManager.appViewBackButtonVisibility = Windows.UI.Core.AppViewBackButtonVisibility.visible;
        }
    }
}

Pour la version en C# (et ma source) c’est par ici

Porting Windows API calls from C# to JavaScript

Windows 10 is still in preview, and as of this writing, a lot of the samples available are written in C#.
The fact that samples are not available in JavaScript does not means that the feature is not available in JavaScript. The only things that may not be available is all topics about XAML controls, like the new InkCanvas, the RelativePanel, and so on. All code related to Windows APIs may be used in JavaScript.

Porting C# code to JavaScript is actually straightforward, especially if you are familiar with WinRT development. Windows APIs (aka WinRT) are projected in all available languages (C++, C#, and JavaScript), using each language paradigms. So, moving C# code to JavaScript is just about changing variable names to lowercase (ex « connection.SendMessageAsync() » => « connection.sendMessageAsync() »), or use the « on… » syntax for event. For example « connection.RequestReceived += someEventHandlerCallback » will convert to « connection.onrequestreceived += someEventHandlerCallback ».

As you can see, this is really easy…