Taking advantage of Continuum with Adaptive UI

With Windows 10, Microsoft introduces Continuum, a feature that allows one to use the phone as the central hub of a PC-like experience with a big screen, a keyboard and, optionally, a mouse.

A Continuum-enabled UWP App should provide a seamless experience when used in both environments. For instance, all the built in applications that ship with Windows 10 are Continuum-enabled Universal Window Platform Apps. Mail, News, Finance, Weather, etc. These are all applications that are usable from the touch-based Phone screen and lighten up with more features and more controls when used from an external display with a mouse and keyboard.

In order to achieve that, a developer can use several new controls that ship with Windows 10. For instance, the SplitView control provides the popular Hamburger-based navigation menu. Also, the RelativePanel is a container that helps create complex layout that can be modified to accommodate more screen real estate by specifying spatial-contraints on its child controls.

Additionally, a developer can take advantage of Adaptive Coding which refers to a set of techniques that help create a single application targeting multiple devices, from small phones to tablets to desktops and more.

There are two sides to Adaptive Coding:

  1. The first one deals with providing the best screen layout and navigation based upon the screen real estate, the current device orientation and the available features.
  2. The second one deals with using features specific to a particular device by detecting whether a particular type or API Contract is present.

In this post, I will highlight how to tackle the first part, thanks to the VisualStateManager class.

The Visual State Manager in Windows 10 takes advantage of Visual State Triggers which are a set of conditions on various states of the application to modify the appearance and organization of one or more controls.

For instance, most examples on this subject show how one can change the color of the background depending upon the current window Width. Several other examples show how one can take advantage of the device orientation to achieve similar results.

In my example, I will show how one can create a custom StateTrigger, i.e. a class that derives from the StateTriggerBase class to detect the current UserInteractionMode. The User Interaction Mode is a value that specifies whether the app is currently being used by using Touch gestures or by using a Mouse and keyboard.

When an App transitions from the Phone screen to an external display thanks to Continuum, the UserInteractionMode changes from Touch to Mouse. That is one of many ways that a developer can take advantage of this feature.

Creating a custom UserInteractionMode state trigger

The idea behind this example is to create a custom class that can be used as a Visual State Trigger in the XAML page. The condition being whether the particular user interaction mode is the one associated with a phone screen – i.e. touch – or the one associated with an external display monitor – i.e. mouse.

This allows to build apps that look like this:

Basic Text Editor App when used on the Phone

Basic Text Editor App when used on the Phone

In your application, create a new file, named UserInteractionModeTrigger and paste the following code:

using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;

public class UserInteractionModeTrigger : StateTriggerBase
{
    ///

<summary>
    /// Initialize a new instance of the <see cref="UserInteractionModeTrigger" /> class.
    /// </summary>


    public UserInteractionModeTrigger()
    {
        Initialize();
    }

    ///

<summary>
    /// Get or set the current UserInteractionMode, i.e. Touch or Mouse.
    /// </summary>


    public string CurrentUserInteractionMode
    {
        get { return (string)GetValue(UIModeProperty); }
        set { SetValue(UIModeProperty, value); }
    }

    public static readonly DependencyProperty UIModeProperty =
        DependencyProperty.Register("UIMode"
            , typeof(string)
            , typeof(UserInteractionModeTrigger),
            new PropertyMetadata("")
            );

    private void Initialize()
    {
        if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
        {
            WindowActivatedEventHandler windowactivated = null;
            windowactivated = (s, e) =>
            {
                Window.Current.Activated -= windowactivated;
                Current_SizeChanged(this, null);
            };

            Window.Current.Activated += windowactivated;
            Window.Current.SizeChanged += Current_SizeChanged;
        }
    }

    private void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e)
    {
        var currentUIMode = UIViewSettings.GetForCurrentView().UserInteractionMode.ToString();
        SetActive(currentUIMode == CurrentUserInteractionMode);
    }
}

This is a simple custom state trigger. Notice that when Initialized, the trigger registers itself on the Activated and SizeChanged events in order to raise a trigger the first time the application is launched. Otherwise, the trigger would only happen during a transition from the Phone screen to the external display.

You can use this call in your app, for instance, like so:

<Page ...
      xmlns:trigg="using:App.Triggers"
...
<Grid>
 
    <!-- The VisualState Groups must be enclosed -- in the first top-level container on a Page. -->

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="UserInteractionModeStates">
            <VisualStateGroup.States>
                <VisualState x:Name="MouseState">
                    <VisualState.StateTriggers>
                        <trigg:UserInteractionModeTrigger CurrentUserInteractionMode="Mouse" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="BottomCommandBar.Visibility" Value="Collapsed" />
                        <Setter Target="Header.Visibility" Value="Collapsed" />
                        <Setter Target="SplitView.(Grid.Row)" Value="0" />
                        <Setter Target="SplitView.(Grid.RowSpan)" Value="2" />
                        <Setter Target="TopCommandBar.Visibility" Value="Visible" />
                    </VisualState.Setters>
                </VisualState>

                <VisualState x:Name="NarrowState">
                    <VisualState.StateTriggers>
                        <trigg:UserInteractionModeTrigger CurrentUserInteractionMode="Touch" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="BottomCommandBar.Visibility" Value="Visible" />
                        <Setter Target="Header.Visibility" Value="Visible" />
                        <Setter Target="SplitView.(Grid.Row)" Value="1" />
                        <Setter Target="SplitView.(Grid.RowSpan)" Value="1" />
                        <Setter Target="TopCommandBar.Visibility" Value="Collapsed" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup.States>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    
</Grid>

The following article has been used as a reference for this post:

Posted in UWP | Tagged , , | Leave a comment

Displaying a Yes, No, Cancel Message Dialog in a Universal Windows Platform (UWP) App

In one of the applications I’m developing, I needed to display a simple Yes, No, Cancel message dialog. Something like this:

In a Universal App, the MessageDialog class is used to display an alert dialog with a set of choices for the user to make. According to the documentation, this class supports up to three commands.

Here is how one could come up with the dialog shown above with the following code:

var title = "Pending changes"
var content = "There are pending changes.\r\nDo you want to save the modifications?";

var yesCommand = new UICommand("Yes", cmd => { ... });
var noCommand = new UICommand("No", cmd => { ... });
var cancelCommand = new UICommand("Cancel", cmd => { ... });

...

var dialog = new MessageDialog(content, title);
dialog.Options = MessageDialogOptions.None;
dialog.Commands.Add(yesCommand);

dialog.DefaultCommandIndex = 0;
dialog.CancelCommandIndex = 0;

if (noCommand != null)
{
    dialog.Commands.Add(noCommand);
    dialog.CancelCommandIndex = (uint)dialog.Commands.Count - 1;
}

if (cancelCommand != null)
{
    dialog.Commands.Add(cancelCommand);
    dialog.CancelCommandIndex = (uint)dialog.Commands.Count - 1;
}

var command = await dialog.ShowAsync();

if (command == yesCommand)
{
	// handle yes command
}
else if (command == noCommand)
{
	// handle no command
}
else
{
	// handle cancel command
}

This all works fine… except on an actual Windows Phone device!

In fact, this code crashes on a phone for no apparent reason. I have debugged and could not find a good reason why this code failed. However, I found out that if I only keep two commands for the dialog, the code works all right.

So, my conclusion is that the MessageDialog class only supports two commands on a Windows Phone device, as opposed to a Desktop or a Tablet.

Thinking about it, it makes sense to use the physical hardware back button on a Windows Phone to simulate Cancel. After all, that would be the most natural choice. So I decided to implement this with the modified code below:

...

var dialog = new MessageDialog(content, title);
dialog.Options = MessageDialogOptions.None;
dialog.Commands.Add(yesCommand);

dialog.DefaultCommandIndex = 0;
dialog.CancelCommandIndex = 0;

if (noCommand != null)
{
    dialog.Commands.Add(noCommand);
    dialog.CancelCommandIndex = (uint)dialog.Commands.Count - 1;
}

if (cancelCommand != null)
{
    // Devices with a hardware back button
    // use the hardware button for Cancel.
    // for other devices, show a third option

	var t_hardwareBackButton = "Windows.Phone.UI.Input.HardwareButtons";

    if (ApiInformation.IsTypePresent(t_hardwareBackButton))
    {
        // disable the default Cancel command index
        // so that dialog.ShowAsync() returns null
        // in that case

        dialog.CancelCommandIndex = UInt32.MaxValue;
    }
    else
    {
        dialog.Commands.Add(cancelCommand);
        dialog.CancelCommandIndex = (uint)dialog.Commands.Count - 1;
    }
}

var command = await dialog.ShowAsync();

if (command == null && cancelCommand != null)
{
    // back button was pressed
    // invoke the UICommand

    cancelCommand.Invoked(cancelCommand);
}

if (command == yesCommand)
{
	// handle yes command
}
else if (command == noCommand)
{
	// handle no command
}
else
{
	// handle cancel command
}

The code first builds the dialog box normally, adding commands. Each time a new command is added, it sets the CancelCommandIndex property to the last one. For a Yes, No dialog, the default Cancel behavior would result in the No command being triggered.

When both a Yes and a Cancel command are present, the code needs to make a choice. If no hardware button is present – for instance, like on a Desktop – the code proceeds normally. In order to detect a feature, the code uses the ApiInformation.IsTypePresent method with “Windows.Phone.UI.Input.HardwareButtons”, which, as its name suggests, returns whether the device has physical hardware buttons.

If a physical hardware back button is present, however, the code does not add the Cancel command. Instead, it sets the CancelCommandIndex property to (uint) -1. This invalid number will make the MessageDialog.ShowAsync() method return null in that case.

After the MessageDialog.ShowAsync() method returns, the code checks to see whether the Cancel command was choosen. Since this command was not actually handled by the MessageDialog class itself, the code invokes it directly for consistency purposes.

Then it proceeds normally to handle the appropriate branch depending upon the user choice.

This code works fine and allows me to build a single App for Desktop and Mobile with the same behavior. However, this code does not produce the absolutely correct behavior when the App is used on a phone but displayed on an external display, such as when taking advantage of the Continuum feature. In that case, I would like the three buttons to be displayed on the dialog box. However, I did not find a solution for this small problem.

Please, let me know in the comments if you know or find out how to achieve this.

Posted in UWP | Tagged , , | Leave a comment

Improving the Hamburger Menu with mouse hover feedback and proper keyboard handling

Last time, we saw how to build a simple Hamburger Menu for navigation in a Universal Windows Platform App starting with Windows 10.

In this post, I will highlight a few modifications that we need to make in order to enhance the appearance of the menu and in order to properly handle keyboard navigation.

Keyboard navigation

A Universal Windows Platform (UWP) App runs on a potentially a large number of devices, including high-end desktop computers. Therefore, it is important to allow the use of the application through proper handling of the keyboard.

Many features come built in the controls available in XAML. For instance, using the Space key allows one to press a button. So it works all right with the Hamburger button and the Radio Buttons.

In my example, however, I would like the Enter key to be used to select a particular option. And I would like the Arrow keys to be used to select amongst the available options.

Open up the MainPage.xaml and add a handler for the KeyDown event:

<Page ... xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" KeyDown="Shell_KeyDown">

    <SplitView x:Name="NavigationPane">
    ...
</Page>

Then, in MainPage.xaml.cs and type in the following code:

///
<summary>
/// Default keyboard focus movement for any unhandled keyboarding
/// </summary>

/// <param name="sender"></param>
/// <param name="e"></param>
private void Shell_KeyDown(object sender, KeyRoutedEventArgs e)
{
    FocusNavigationDirection direction = FocusNavigationDirection.None;

    switch (e.Key)
    {
        // both Space and Enter will trigger navigation

        case Windows.System.VirtualKey.Space:
        case Windows.System.VirtualKey.Enter:
            {
                var control = FocusManager.GetFocusedElement() as Control;
                var option = control as RadioButton;
                if (option != null)
                {
                    var automation = new RadioButtonAutomationPeer(option);
                    automation.Select();
                }
            }
            return;

        // otherwise, find next focusable element in the appropriate direction

        case Windows.System.VirtualKey.Left:
        case Windows.System.VirtualKey.GamepadDPadLeft:
        case Windows.System.VirtualKey.GamepadLeftThumbstickLeft:
        case Windows.System.VirtualKey.NavigationLeft:
            direction = FocusNavigationDirection.Left;
            break;
        case Windows.System.VirtualKey.Right:
        case Windows.System.VirtualKey.GamepadDPadRight:
        case Windows.System.VirtualKey.GamepadLeftThumbstickRight:
        case Windows.System.VirtualKey.NavigationRight:
            direction = FocusNavigationDirection.Right;
            break;

        case Windows.System.VirtualKey.Up:
        case Windows.System.VirtualKey.GamepadDPadUp:
        case Windows.System.VirtualKey.GamepadLeftThumbstickUp:
        case Windows.System.VirtualKey.NavigationUp:
            direction = FocusNavigationDirection.Up;
            break;

        case Windows.System.VirtualKey.Down:
        case Windows.System.VirtualKey.GamepadDPadDown:
        case Windows.System.VirtualKey.GamepadLeftThumbstickDown:
        case Windows.System.VirtualKey.NavigationDown:
            direction = FocusNavigationDirection.Down;
            break;
    }

    if (direction != FocusNavigationDirection.None)
    {
        var control = FocusManager.FindNextFocusableElement(direction) as Control;
        if (control != null)
        {
            control.Focus(FocusState.Programmatic);
            e.Handled = true;
        }
    }
}

The code is divided into two parts.

The first part handles the Space and Enter key so that it selects the currently selected button. In order to do that, one has to use the RadioButtonAutomationPeer class to programmatically select the associated RadioButton. That way, when you press Enter, the RadioButton is selected and this, in turn, triggers navigation to the appropriate page.

The second part of the code handles the Arrow keys and equivalent keys coming from controllers and game pads. This searches for and set the focus to the next focusable element available in the given direction. For instance, if the currently selected option is the Option 1 RadioButton, a press on the Down key will find the Option 2 RadioButton. That way, selecting a given control using the Arrow keys is very simple.

The last modification we need to make is to fix the incorrect display of the focus rectangle when the SplitView is in Compact DisplayMode. Because the Compact display mode clips the content of the navigation pane, the result is somewhat unexpected:

In MainPage.xaml.cs modify the implementation of the HamburgerButton_Click event handler and add a call to a method that resizes the controls hosted on the SplitView pane:

private void HamburgerButton_Click(object sender, RoutedEventArgs e)
{
    NavigationPane.IsPaneOpen = !NavigationPane.IsPaneOpen;

    ResizeOptions();
}

///
<summary>
/// Fix the clipped focus rectangle when SplitView DisplayMode is Compact
/// </summary>

private void ResizeOptions()
{
    // calculate the actual width of the navigation pane

    var width = NavigationPane.CompactPaneLength;
    if (NavigationPane.IsPaneOpen)
        width = NavigationPane.OpenPaneLength;

    // change the width of all control in the navigation pane

    HamburgerButton.Width = width;

    foreach (var option in NavigationMenu.Children)
    {
        var radioButton = (option as RadioButton);
        if (radioButton != null)
            radioButton.Width = width;
    }
}

Mouse Hover feedback

In to improve the feedback to the user as to whether a particular control can be selected or pressed, one has to change the color of the control when the mouse hovers above it. Because we already have some styles for the HamburgerButton and the navigation RadioButton controls, it is very easy to add this feature.

A quick look into the default generic.xaml file that ships with the SDK alllows one to copy and paste the default Template for a given control. This file is located in the following folder:

For instance, the default Button template defines the following Common States such as Normal, PointOver Pressed and Disabled. Likewize, the default RadioButton Template defines the same Common States (because it is also a Button) as well as the following CheckedStates such as Checked, Unchecked and Indeterminate.

We are only interested in the PointerOver and Pressed states for the HamburgerButton and the RadioButton controls.

So, open up Themes\Generic.xaml and add the following states in both styles MenuItemButtonStyle and NavigationButtonStyle:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="Common">
        <VisualState x:Name="Normal" />
        <VisualState x:Name="PointerOver">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="RootGrid"
                    Storyboard.TargetProperty="Background">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}" />
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
        <VisualState x:Name="Pressed">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="RootGrid"
                    Storyboard.TargetProperty="Background">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}" />
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
        <VisualState x:Name="Disabled" />
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Posted in UWP | Tagged , , | Leave a comment

Building a Hamburger Menu for your Universal App

One of the first thing to do when building a Universal Windows Platform (UWP) Application is to choose how the application will present its features to the user. The Hamburger Menu is one of the most popular designs for implementing navigation in a universal app. Its use is pervasive across all Microsoft apps and a lot of third-party apps as well. Evidently, the SafetyBox App will also feature navigation based upon a Hamburger Menu.

I have found a lot of information about building such a feature in my app. Specifically, the following articles or samples were used as inspiration for this article:

However, in this article, I will try to present a consolidated approach that makes sense and present the concepts in the order I stumbled upon when trying to implement this menu in my own app.

Creating the “Chrome” of the App in a Shell.xaml Page

In order to power a Hamburger-based navigation menu, one has to use the SplitView control, designed to separate the contents of a page into two parts:

  • The left part, called the navigation Pane, consisting in the hamburger menu itself.
  • The right part, designed to host a Frame, consisting in any page that the user wants to navigate to.

The navigation pane can be invisible, or displayed in Compact or Open mode. The Compact mode typically displays only the hamburger button itself and the navigation options in the form of icons. The Open mode diplays additional text for the navigation options, as well as a richer set of interactive options if the application requires it.

A default project for building universal applications create an App.xaml application object as well as a MainPage.xaml page. One of the first task when implementing the Hamburger menu is to change the MainPage.xaml to act as a Shell that provides navigations to other pages.

There are several options for laying out the Hamburger menu.

One popular option is the one used by most builtin MSN/Live Apps, such as News, Finances, Weather, etc. This is done with the following layout, where you can notice that the Hamburger button is actually not part of the SplitView pane.

A snapshot of the News MSN App where the hamburger button is not part of the SplitView pane.

Another option is to include the Hamburger button inside the SplitView pane. This approach is used by the Groove App, for instance.

A snapshot of the Groove Music App where the hamburger button is part of the SplitView pane.

In this article, I will present a solution for implementing the latter option, similar to the Groove Music App.

Another choice to make is how to implement the SplitView pane menu items.

I have personally chosen to use RadioButton controls for several reasons. First, conceptually, the options in a SplitView pane can be thought of as a group of mutually exclusive options. Second, it is very easy to apply custom styling to a RadioButton via a redefined control template. Since styling is easy, it is also easy to include support for changing the colors on mouse/pointer hover.

Another option would have been to use a ListView control with single selection enabled, for instance. A ListView is a bit more cumbersome to use, however, because have to use a custom class that represent ListView items and use a DataTemplate to apply styling and custom behavior. Also, one has to include special code to support navigating the list with the keyboard without triggering item selection.

With that said, let’s dive into the code!

Starting from a blank project for a universal application, make the following changes:

  1. First, you may optionally want to rename MainPage.xaml to Shell.xaml.
  2. Open MainPage.xaml (or Shell.xaml), and replace the empty Grid control with the following code:
<SplitView x:Name="NavigationPane" DisplayMode="CompactInline">
  <SplitView.Pane>

    <Grid>

      <Grid.RowDefinitions>
        <RowDefinition Height="44" />
        <RowDefinition Height="*"/>
      </Grid.RowDefinitions>

      <Button x:Name="HamburgerButton" Grid.Row="0" Style="{StaticResource MenuItemButtonStyle}" Tag="& #xE700;" Click="HamburgerButton_Click" />

      <StackPanel x:Name="NavigationMenu" Orientation="Vertical" Grid.Row="1">
        <RadioButton x:Name="Option1"
           GroupName="Group1"
           Style="{StaticResource NavigationButtonStyle}"
           Tag="& #xE76E;"
           Checked="Option1Button_Checked"
           Content="Option 1"
           />
        <RadioButton x:Name="Option2"
           GroupName="Group1"
           Style="{StaticResource NavigationButtonStyle}"
           Tag="& #xE76E;"
           Checked="Option2Button_Checked"
           Content="Option 2"
           />
      </StackPanel>

    </Grid>

  </SplitView.Pane>
  <SplitView.Content>

    <Frame x:Name="Content">
      <Frame.ContentTransitions>
        <TransitionCollection>
          <NavigationThemeTransition>
            <NavigationThemeTransition.DefaultNavigationTransitionInfo>
              <EntranceNavigationTransitionInfo/>
            </NavigationThemeTransition.DefaultNavigationTransitionInfo>
          </NavigationThemeTransition>
        </TransitionCollection>
      </Frame.ContentTransitions>
    </Frame>
  </SplitView.Content>
</SplitView>

This code uses the otherwise unused Tag property of XAML controls to store the icon associated with a particular option. This icon is designated with a code that maps to the character code using the Windows 10 font named Segoe MDL Assets 2.

  1. Open MainPage.xaml.cs (or Shell.xaml.cs) and paste the following code:
public Frame AppFrame { get { return Content; } }

private void Option1Button_Checked(object sender, RoutedEventArgs e)
{

}

private void Option2Button_Checked(object sender, RoutedEventArgs e)
{

}

private void HamburgerButton_Click(object sender, RoutedEventArgs e)
{
    NavigationPane.IsPaneOpen = !NavigationPane.IsPaneOpen;
}

The layout code makes use of static resources to style the hamburger button as well as the radio buttons that act as navigation options:

  1. Open App.xaml and past the following code to enable access to additional resources:
<Application.Resources>
  <ResourceDictionary>

    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="Themes/Generic.xaml"/>
    </ResourceDictionary.MergedDictionaries>

  </ResourceDictionary>
</Application.Resources>


  1. Create a file named Themes\Generic.xaml to host the resources:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


<Style TargetType="Button" x:Name="MenuItemButtonStyle" x:Key="MenuItemButtonStyle">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}"/>
    <Setter Property="MinWidth" Value="{ThemeResource SplitViewCompactPaneThemeLength}" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">

          <Grid x:Name="RootGrid">

            <Grid.RowDefinitions>
              <RowDefinition Height="44" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="48" />
              <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
        
            <!-- use extra left margin to align the icon with NavigationButtonStyle'd controls -->
            <FontIcon Grid.Column="0"
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                Margin="12,8,8,8"
                FontFamily="{ThemeResource SymbolThemeFontFamily}"
                Glyph="{TemplateBinding Tag}"
                />
            <TextBlock Grid.Column="1"
                VerticalAlignment="Center"
                HorizontalAlignment="Left"
                Margin="8,8,8,8"
                Text="{TemplateBinding Content}"
                />
          </Grid>

        </ControlTemplate>
      </Setter.Value>
    </Setter>

  </Style>

<Style TargetType="RadioButton" x:Name="NavigationButtonStyle" x:Key="NavigationButtonStyle">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}"/>
    <Setter Property="MinWidth" Value="{ThemeResource SplitViewCompactPaneThemeLength}" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="RadioButton">

          <Grid x:Name="RootGrid">

            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CheckedStates">
                <VisualState x:Name="Checked">
                  <Storyboard>
                    <ColorAnimation Storyboard.TargetName="Brush" Storyboard.TargetProperty="Color" From="{Binding Path=Background}" To="Blue" Duration="0:0:0" FillBehavior="HoldEnd" />
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Unchecked" />
                <VisualState x:Name="Indeterminate" />
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Grid.RowDefinitions>
              <RowDefinition Height="44" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="4" />
              <ColumnDefinition Width="44" />
              <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Rectangle Grid.Column="0">
              <Rectangle.Fill>
                <SolidColorBrush x:Name="Brush" Color="{Binding Path=Background}" />
              </Rectangle.Fill>
            </Rectangle>

            <FontIcon Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,8,8,8" FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="{TemplateBinding Tag}" />
            <TextBlock Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="8,8,8,8" Text="{TemplateBinding Content}" />

          </Grid>

        </ControlTemplate>
      </Setter.Value>
    </Setter>

  </Style>

</ResourceDictionary>

Two styles are defined in the Generic.xaml file.

The second style, named NavigationButtonStyle, is targeting RadioButton controls in the Hamburger menu. This style defines a layout with three columns. From left to right, one finds a) a selection-rectangle that highlights when the particular option is selected, b) an icon and, c) a text, displayed when the SplitView pane is open. This style includes visual triggers using a ColorAnimation to highlight the selection rectangle in blue when the particular option is selected.

The first style, named MenuItemButtonStyle, is targeting regular Button controls. In particular, this is the style used by the Hamburger button itself. You will notice that is uses a two-columns layout, with an icon and a text. Notice that the icon’s left margin is adjusted so as to be aligned with icons displayed by the first style.

At this stage, you should have a basic working application:

A basic universal app with a popular Hamburger navigation menu

In the next post, I will walk you through adding proper mouse/pointer hover feedback and handling navigation using the keyboard.

Posted in UWP | Tagged , | Leave a comment

Building Universal Windows Platform (UWP) App for Windows 10

You may have noticed it’s been a long time since I posted on this blog.
As a matter of fact, I have been really busy working on expanding our Middleware as a Service Platform at Moskitos.

At the same time, since the unveiling of Windows 10, I have been really excited about Universal Windows apps and wanted to contribute some ideas on this.
Although my day to day job is still very much grounded in the fields of Integration and Azure, I would like to primarily focus my interest around building Apps for the Windows 10 Universal Windows Platform on my spare time.

Announcing the Safety Box App

To this end, I’m setting up an open-source project on GitHub.
The purpose of the SafetyBox App is to be a Universal client for KeePass .kdbx database files.

I have been a long time user of the iPhone where one of the best password manager app is AgileBits’ 1Password.
Since I recently switched to using a Windows Phone, I figured I’d use a similar app from the store. However, I found the offering to be very poor. I found that the 1Password app only works in read-only mode and is lacking compared to its iOS counterpart. So I switched to using KeePass at the same time. Again, there are a couple of applications in the Store for KeePass, but they are either old or not as feature-rich as I may like them to be. Additionally, I think the user experience for these apps can be improved.

That’s why I decided to share my contributions as an open-source project.

Since I’m new to building XAML apps – I must have lived on another planet during the Silverlight and Windows 8 eras – I have a a lot to learn!
Anyway, I have reserved a name in the Windows Store and this blog will record my attempt at publishing the application to the Windows Store in due course…

Thanks for reading.

Posted in UWP | Leave a comment

Building a Simple FILE to FILE Integration with Crosscut

One of the first thing one tries when evaluating an integration platform, is a simple file to file integration. This Managed File Transfer is the moral equivalent of an “Hello World” program for integration and middleware platforms.

In this post, I will walk through how one does implement a simple FILE to FILE scenario with Crosscut. In the following post, I will outline the technical challenges and talk about the Azure components used under the hood to build such a scenario.

In the following weeks, I will use this dual post approach to explain our technical journey in building Crosscut. One post will outline how the scenario appears to customers and integration partners, while the next will delve into technical details.

So, let’s see how our integration partners use Crosscut to build a simple integration.

Building Publication and Subscription Ports

Like many integration platforms, Crosscut relies on a publish/subscribe integration pattern to transport messages from a source system to a target system. Of course, it also relies on the Message Endpoint pattern, known in Crosscut as Connectors to acquire data from a source system and transmit data to a target system.

So the first thing to do is to build a couple of ports, one that will detect files on the source system and another that will transmit this file to a target system.

So first, connect to Crosscut:

Jump to the “Developer” mode in the portal. That’s where a developer will design data integrations. The other two modes are “Monitoring”, where a user can gain insights into how the integrations behave – such as Message Interchanges, Event Logs, etc. – and “Management”, where an administrator create users and grant permissions to various parts of the Platform.

Select the “Publication Ports” menu on the left, and click on the “New” button to create a new publication port.

Give a meaningful name to the port and click on the “Select a Connector” box.

In this case, select the FILE inbound connector.

By default, only the required properties are shown when configuring a connector. Type in the location of the folder from which files will be taken on the source system, and click “Save”.

Back on the publication port configuration screen, notice that a “Request Pipeline” box is shown. This indicates that the publication port is a One-Way port and that an optional sequence of processing can be applied to the message before being submitted to Crosscut.

In this case, leave the box empty, and click “Save”.

In order to configure the subscription port, select the “Subscription Ports” menu on the left, and follow the same steps. Just select the outbound FILE connector and choose an appropriate location for a folder in which files will be transmitted on the target system.

Creating and Activating a Data Integration Flow

In order to build the data integration, one must link the publication port to the subscription port. Select the “Flows” menu on the left, and click the “New Flow” button to create a new flow.

Select the publication and subscription ports created in the previous steps, and use drag and drop to create a link from the publication port to the subscription port. This instructs Crosscut that whenever a message is published by that particular publication port, a copy should be delivered to the specified subscription port.

It is also possible to click on the link to set Subscription Filters in order to select only a subset of all the messages published by the publication port. But for this post, the subscription filter is a catch-all filter.

A flow must be activated before messages can be delivered to Crosscut.
Click the hamburger menu from the flow tile and select “Activate”. This operation is asynchronous, because it creates all the necessary infrastructure on Azure to allow for message delivery.

Once the flow is activated, the publication and subscription ports must be hosted in some sort of executable process, in order for the data integration to effectively take place.

Creating a Group for Hosting Publication and Subscription Ports

The executable process in which publication and subscription ports are hosted is part of a logical Group that is created and managed centrally in Crosscut. Each group can contain one or more instances of an executable, each of which hosts the publication and subscription ports that are associated with it.

Crosscut comes with a builtin Group, named Cloud Connect to host publication ports and subscription ports that connect to online systems, such as Salesforce.com, or an FTP server, for instance. In order to host publication and subscription ports that connect to a LOB system, one must create one or more dedicated groups.

From the left side, select the “Group” menu and click “New” to create a new Group.

Once a group is created, one or more ports must be associated with it. In a typical scenario, the publication and subscription ports would be associated with differents groups. Each group would map to an instance of a process that runs on a different machine. In this post, I choose to have a single group for demonstration purposes.

The ports associated with a group can be Started or Stopped. Obviously, for messaging to flow from one port to another, the ports must be started…

Running the Data Integration

All is now configured to run the data integration. The remaining steps involve downloading and running an instance of the executable process that hosts the publication and subscription ports associated with the group configured in the previous section of this post.

This executable process is named OnPrem-Connect because it is typically deployed on a machine running on-premises. Click on the Cloud icon on the right hand side of the group caption to download a setup program that install a pre-configured instance of the executable process.

Complete the installation wizard and wait for the service to start and register itself to the Crosscut portal.

Once registered, an instance of the OnPrem-Connect executable is identified by a green indicator on the group caption bar. There can be other instances of the same group, running on other machines for redundancy and performance purposes.

That’s it.

To complete this post, when a file is dropped in the publication folder…

… it is taken by the OnPrem-Connect instance that hosts the publication port and published to Crosscut as a message.

Once subscribed to, the message is then transferred to the OnPrem-Connect instance that hosts the subscription port, which delivers its payload to the target folder.

Here was a quick overview of a simple FILE to FILE integration scenario with Crosscut.

Posted in Crosscut | Tagged , | Leave a comment

Introducing Crosscut® by Moskitos™ an Exciting new IPaaS offering

For the past two years and a half, Jérémie and I have contributed in creating and growing Moskitos, an Independant Cloud Service Provider where we are building exciting new solutions. In particular, as a Software Architect and CTO at Moskitos, I have been busy designing and building a new Integration Platform as a Service (IPaaS).

Our platform is called Crosscut.

Crosscut Integration Platform as a Service Overview

Crosscut is a middleware solution that runs in the cloud and manages data and process integration. It is based upon many of the same principles found in BizTalk Server but we have implemented our simplified solution from scratch using many services provided by Microsoft Azure. Currently, our platform is used internally by our consultants, who deliver integration projects for our clients. It is also targetted at select partners and cloud service providers that want to push their own offering but have to overcome the fact that some of their customers may not realize they should invest in an integration platform.

In the following weeks, I will post on this blog to highlight our journey building Crosscut.

The focus of this blog did not change. I will still document the technical challenges that we faced, the choices that we made and hopefully post some tips and tricks that may apply to a wide audience.

Crosscut Portal Screenshots

Posted in Non classé | Tagged , , , | Leave a comment