Building a Hamburger Menu for your Universal App

One of the first thing to do when building a Universal Windows Platform (UAP) 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 (UAP) 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 , , , | 1 Comment

Integrating NLog with Azure Cloud Service Diagnostics

NLog is a popular open-source logging Framework for .Net applications. In my opinion, it is very flexible and is more feature rich than, say, the builtin .Net tracing Framework. For instance, NLog supports asynchronous logging. It also supports flexible trace formatting an has auto-archiving mechanism that I find very useful.

Some articles have already been discussing how using NLog from an Azure Cloud Service could work. Most of these articles instruct you to make NLog log to the builtin .Net Trace sources and, from there, the default support for Azure diagnostics kicks in and persist the logs to a preconfigured Storage account.

However, this approach has the drawback that any Tracing done in your application will also end up in the persisted logs.

In the project I’m working on, I could not use this approach because I wanted to have multiple distinct trace files. This project implements some kind of a Process Runner and I wanted to capture and persist each process’s STDOUT and STDERR streams in a dedicated trace log.

So the strategy I ended up following consists in implementing the following steps:

  1. Write NLog messages to a dedicated file. One file per logger.
  2. Use NLog auto-archiving feature to periodically archive traces to a particular folder.
  3. Configure Azure diagnostics to persist archived traces to a Storage account.

In practice, this works really well.

The remainder of this post will walk you through how to configure you Cloud Service in order to persist NLog file traces to an Azure Storage account.

Writing NLog traces to local storage

First, you need to configure local storage for your Cloud Service, so that NLog can write traces to the filesystem.

For reference, your Cloud Service’s ServiceDefinition.csdef file is modified like so:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Host" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2014-06.2.4">
  <WorkerRole name="WorkerRole" vmsize="Small">
    <LocalResources>
      <LocalStorage name="logs" cleanOnRoleRecycle="true" />
    </LocalResources>
  </WorkerRole>
</ServiceDefinition>

Next, NLog needs to know where to write the log files. The easiest way I found, was to create an environment variable that refers to the local storage location and use that variable in NLog’s configuration. In order to define an environment variable, you need to manually edit your Cloud Service’s ServiceDefinition.csdef file like so:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Host" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2014-06.2.4">
  <WorkerRole name="WorkerRole" vmsize="Small">
    <Runtime>
      <Environment>
        <Variable name="NLOGDIR">
          <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/LocalResources/LocalResource[@name='logs']/@path" />
        </Variable>
      </Environment>
    </Runtime>
  </WorkerRole>
</ServiceDefinition>

This modification creates an environment variable named NLOGDIR that points to the location of each instance’s local storage resource directory. Having this done in the Service Definition ensures that the environment variable is created before the role starts, so that NLog can take advantage of it during its configuration.

In NLog’s configuration, use the environment variable as the location of the log files.

<target name="App" xsi:type="File"
  lineEnding="Default" autoFlush="true" keepFileOpen="false" concurrentWrites="true" 
  fileName="${environment:variable=NLOGDIR}\ApplicationLog.txt"
  archiveFileName="${environment:variable=NLOGDIR}\archive\ApplicationLog_${date:format=yyyymmddHH}_{#####}.log"
  archiveEvery="Minute" archiveNumbering="sequence" maxArchiveFiles="720"
  >
...

Persisting NLog traces to an Azure Storage account

In order to persist trace files to an Azure Storage account, you must configure Azure diagnostics to periodically transfer the contents of the trace files from the local storage to a preconfigured Azure Storage account.

First, the Azure Diagnostics Module must be enabled for your Cloud Service. This is usually done by default when creating the Cloud Service project from Visual Studio.

Make sure to configure an appropriate Connection String pointing to an Azure Storage account where trace files will be persisted. During development, of course, the development storage will do.

In theory, you can configure Azure diagnostics declaratively, using the Diagnostics.wadcfg file, stored under your role node in Solution Explorer.

In order for the configuration to take effect, this file must be included, or better linked, to the role project. Make sure to set the “Copy to Output Directory” property of this file to “Copy always” or “Copy if newer”.

The contents of the Diagnostics.wadcfg file must be updated so that the Azure Diagnostics monitor can transfer the contents of the local storage directory to a specified blob container in the configured Storage Account.

<DiagnosticMonitorConfiguration configurationChangePollInterval="PT1M" overallQuotaInMB="4096" xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration">
  <DiagnosticInfrastructureLogs />
  <Directories scheduledTransferPeriod="PT1M" >
    ...
    <DataSources>
      <DirectoryConfiguration container="wad-custom-container" directoryQuotaInMB="1024">
        <LocalResource name="logs" relativePath=".\archive" />
      </DirectoryConfiguration>
    </DataSources>
  </Directories>

Make sure to not exceed the overall quota otherwise the Diagnostics Monitor will crash upon startup. Thanks Jérémie for the time taken to troubleshoot this!

Posted in Tips, Windows Azure | Tagged , , | 3 Comments

Microsoft® MVP Integration 2015 !

For the fifth consecutive year, I have been receiving the Microsoft Most Valuable Professional award. I’m proud to be part of the Microsoft Integration community for another year.

Congratulations to the 2015 Microsoft MVP!

This year, I had the great pleasure to attend the MVP Summit, so I’m glad I will have the opportunity to meet some of you guys in the community again.

I’m looking forward to some exciting news in the domain of Micro Services in particular and the interactions between the Integration space and the Cloud Computing in general.

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

Nouvel article sur l’adoption du Cloud en entreprise dans le Magazine Programmez !

Le marché du Cloud Computing a déjà séduit de très nombreuses entreprises. Pourtant, plusieurs études indépendantes montrent que l’usage de l’informatique dématérialisée dans les entreprises est loin d’être aussi répandu qu’on pourrait le penser.

C’est ainsi que commence l’article que j’ai co-écrit avec Jérémie.

Il est paru dans le numéro de novembre 2014 du Magazine Programmez !
Je vous invite à le lire !

Posted in Article / Presse | Tagged | Leave a comment