Category Archives: UX

Introducing WinUI ItemsRepeater and Friends

In this article we’ll build a fluent NetFlix-inspired single-page UWP app on top of iTunes Movie Trailers data. The app uses some of the newer WinUI controls such as ItemsRepeater, TeachingTip, CommandBarFlyout, as well as classic XAML elements like MediaPlayerElement, acrylic brushes and animation. 

The app allows you to scroll horizontally and vertically through a list of movies per genre, select a movie, and play its trailer. The app is fully functional in touch, mouse, and keyboard mode. Here’s how it looks like – we decided to call it XamlFlix (the runners-up names were .NET Flix and WinUI tunes):


In a previous blog post we described WinUI as the future of XAML development.  For more details, take a look at this great session on “Windows App Development Roadmap: Making Sense of WinUI, UWP, Win32, .NET” from the Ignite event. For a summary of this session, check Paul Thurrot’s article from which we borrowed the following illustration:


Getting the data

Our sample app starts with getting the most recent iTunes Movie Trailers content. It is exposed as a public XML document that looks like this:


We defined a class to represent a movie, with its title and the whereabouts of its poster image and QuickTime trailer:

public class Movie
    public string Title { get; set; }

    public string PosterUrl { get; set; }

    public string TrailerUrl { get; set; }

For convenience, movies are grouped by genre. Here’s the corresponding class:

public class Genre
    public string Name { get; set; }

    public List<Movie> Movies { get; set; }

Using HttpClient.GetStringAsyc() we fetch the XML from the internet. Then we Parse() it into an XDocument. First we get the genre names through a fancy XPATH expression using XPathSelectElements():

using (var client = new HttpClient())
    xml = await client.GetStringAsync("");

var movies = XDocument.Parse(xml);

var genreNames = movies.XPathSelectElements("//genre/name")
                .Select(m => m.Value)
                .OrderBy(m => m)

Then we use some more of this XPATH and LINQ magic (Eat my shorts, JSON!) to query the movies per genre –a movie may appear in more than one genre- and immediately populate all the element collections:

foreach (var genreName in genreNames)
    _genres.Add(new Genre()
        Name = genreName,
        Movies = movies.XPathSelectElements("//genre[name='" + genreName + "']")
            .Select(m => new Movie()
                Title = m.XPathSelectElement("info/title").Value,
                PosterUrl = m.XPathSelectElement("poster/xlarge").Value,
                TrailerUrl = m.XPathSelectElement("preview/large").Value
            //.OrderBy(m => m.Title)

Here’s the DataTemplate that represents a Movie in the app. It’s just an image that we made clickable and focusable by placing it inside a button:

        <DataTemplate x:Key="MovieTemplate"
            <Button Click="Movie_Click"
                <Image Source="{x:Bind PosterUrl}"
                       ToolTipService.ToolTip="{x:Bind Title}">

Adding some WinUI components

Let’s bring in some WinUI components to create the visual foundation of the app. These components live in the Microsoft.UI.Xaml NuGet package:


After adding the NuGet package, don’t forget to import its styles and other WinUI resources. App.xaml is the best place to do this:

            <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
            <!-- Other merged dictionaries here -->
        <!-- Other app resources here -->
        <x:Double x:Key="ContentDialogMaxWidth">800</x:Double>

Here comes ItemsRepeater

XamlFlix is built around collections: it displays a collection of genres that each display a collection of movies. ItemsRepeater is an ideal host for this: it’s a WinUI element that is designed to be used inside custom controls that display collections. It does not come with a default UI and it provides no policy around focus, selection, or user interaction. It supports virtualization so it allows you to deal with very large collections out of the box.

The main beef of the app’s UI are ItemsRepeater controls: there’s one that repeats the genres vertically, and genre comes a horizontal repeater on the movies.

We started with defining two  reusable StackLayout resources: 

<controls:StackLayout x:Key="HorizontalStackLayout"
                        Orientation="Horizontal" />
<controls:StackLayout x:Key="VerticalStackLayout"
                        Spacing="0" />

An ItemsRepeater is a data-driven panel that does not come with its own scrolling infrastructure, so you may need to wrap it in a ScrollViewer. Here’s the declaration of the repeater for the Genre instances:

<ScrollViewer VerticalScrollBarVisibility="Auto"
    <controls:ItemsRepeater x:Name="GenreRepeater"
                            ItemTemplate="{StaticResource GenreTemplate}"
                            Layout="{StaticResource VerticalStackLayout}"
                            VerticalAlignment="Stretch" />

Each genre has its name displayed on top of a horizontal list of Movie instances – again implemented as an ItemsRepeater inside a ScrollViewer:

<DataTemplate x:Key="GenreTemplate"
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        <Image VerticalAlignment="Stretch"
                Margin="6 0 0 0"
                Grid.RowSpan="2" />
        <TextBlock Foreground="Silver"
                    Margin="66 0 0 0"
                    Text="{x:Bind Name}" />
        <ScrollViewer HorizontalScrollBarVisibility="Visible"
                        Margin="66 0 0 0"
            <controls:ItemsRepeater ItemsSource="{x:Bind Movies}"
                                    ItemTemplate="{StaticResource MovieTemplate}"
                                    Layout="{StaticResource HorizontalStackLayout}" />

After the content was loaded, we set its items source programmatically:

GenreRepeater.ItemsSource = Genres

The page then looks like this:


Let’s move our focus to the behavior now.

On a touch screen the page reacts appropriately to horizontal and vertical panning. Mouse scrolling is a bit problematic: the movie repeaters take almost all the screen area and hence they get the mouse input and only trigger horizontal scrolling. So we decided to place a film strip on the left. It creates an area that facilitates vertical scrolling through the genres.

Hello TeachingTip

The mouse behavior is not very intuitive for first-time users, so we added a TeachingTip –a WinUI Flyout with an arrow- to draw the user’s attention to the film strip on the left.

Here’s its XAML declaration:

<controls:TeachingTip x:Name="ScrollTeachingTip"
                        Target="{x:Bind FakeTarget}"
                        Title="I looks like you are trying to scroll."
                        Subtitle="With the mouse on this filmstrip you'll scroll vertically."
        <controls:SymbolIconSource Symbol="Sort" />

The TeachingTip needs to point to the film strip as its a Target. While visually the strip looks like a whole, it’s actually composed of multiple images: it’s repeated per genre. That makes it hard to use as target for the teaching tip – at least declaratively.

We provided an alternative Target by placing a UI-less control center left of the page:

<ContentControl x:Name="FakeTarget"
                Grid.Row="2" />

Here’s the result, the teaching tip points right to the middle of the film strip:


We couldn’t resist creating a version with an image of Clippy as HeroContent:


It doesn’t make sense to pop-up the tip while the movie images are still loading, so we delayed its appearance:

await Task.Delay(2000);
ScrollTeachingTip.IsOpen = true;

We covered both touch and mouse input for navigation. Let’s now take a look at keyboard input.

To our great surprise we observed that the page already behaved properly on keyboard input. Here’s how navigation with the arrow keys looks like – not bad for a lightweight control that does not support selection. The visual border around the movie is the focus rectangle of the button in the Movie data template:


To highlight the movie under the mouse cursor, our first attempt was a ToolTip with the title. It’s hardly visible and it feels like HTML. Here’s an example (hint: it’s on Spice in disguise):


We went for a more fluent experience. When digging through the awesome XAML Controls Gallery we found this nice sample that animates the size of a button on hover (don’t try it out here, it’s just a screenshot):


We decided to subtly grow and shrink the image under the mouse cursor on hovering. It only required a straight copy/paste from the gallery sample code. The code uses the Compositor to hook a SpringVector3NaturalMotionAnimation to the scale of the image. We increase it by 2% on PointerEntered and then shrink back on PointerExited:

private Compositor _compositor = Window.Current.Compositor;
private SpringVector3NaturalMotionAnimation _springAnimation;

private void CreateOrUpdateSpringAnimation(float finalValue)
    if (_springAnimation == null)
        _springAnimation = _compositor.CreateSpringVector3Animation();
        _springAnimation.Target = "Scale";

    _springAnimation.FinalValue = new Vector3(finalValue);

private void Element_PointerEntered(object sender, PointerRoutedEventArgs e)
    // Scale up a little.

    (sender as UIElement).StartAnimation(_springAnimation);

private void Element_PointerExited(object sender, PointerRoutedEventArgs e)
    // Scale back down.

    (sender as UIElement).StartAnimation(_springAnimation);

Here’s how the result looks like – the real animation is a lot smoother that the animated gif suggests:


That looks decent, no? Let’s add some more functionality now.

Introducing CommandBarFlyout

The CommandBarFlyout is another WinUI control that lives up to its name: it is literally a CommandBar in a Flyout. It groups AppBarButton instances in primary and secondary commands that are applicable to a specific UI element.

XamlFlix uses a CommandBarFlyout to display the possible actions for the selected movie: play, buy, rate, …. For the sake of simplicity we hooked them all to the same event handler: whatever menu you select, you always get to play the movie trailer.

Here’s the declaration of the movie menu:

<controls:CommandBarFlyout x:Name="MovieCommands"
    <AppBarButton Label="Play"
                    Click="Element_Click" />
    <AppBarButton Label="Info"
                    Click="Element_Click" />
    <AppBarButton Label="Download"
                    Click="Element_Click" />
        <AppBarButton Label="Buy"
                        Click="Element_Click" />
        <AppBarButton Label="Rate"
                        Click="Element_Click" />

The control comes with several FlyoutShowOptions to configure position, placement, and behavior. Here we define it to appear on top of the image, in an expanded state and grabbing the focus. The ShowAt() method is called when a button in a movie data template is clicked. It opens the menu for the targeted UI element:

private void Movie_Click(object sender, RoutedEventArgs e)
    FlyoutShowOptions options = new FlyoutShowOptions();
    options.ShowMode = FlyoutShowMode.Standard;
    options.Placement = FlyoutPlacementMode.Top;

    MovieCommands.ShowAt(sender as FrameworkElement, options);

This is how the menu looks like in XamlFlix (on top of Top Gun):


Here’s MediaPlayerElement

For playing the movie trailer there are not too much options. We went for the classic UWP MediaPlayerElement and placed it in a ContentDialog:

<ContentDialog x:Name="MediaPlayerDialog"
        <TextBlock x:Name="TitleText"
                    Margin="0 0 0 20" />
        <MediaPlayerElement x:Name="Player"
                            AutoPlay="True" />

The dialog needs more space than the maximum of 548 pixels that a popup normally gets in UWP, so you have to override ContentDialogMaxWidth in app.xaml:

<x:Double x:Key="ContentDialogMaxWidth">800</x:Double>

When an element of the command bar flyout is clicked, we open the dialog and create a MediaSource from the trailer’s URL. We need to Hide() the command bar flyout, since it lives in the same layer as the dialog:

private async void Element_Click(object sender, RoutedEventArgs e)
    // It stays on top of the dialog.

    var movie = (sender as FrameworkElement)?.DataContext as Movie;
    var source = MediaSource.CreateFromUri(new Uri(movie.TrailerUrl));

    TitleText.Text = movie.Title;
    Player.Source = source;
    await MediaPlayerDialog.ShowAsync();

private void MediaPlayerDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)
    // Prevent the player to continue playing.
    Player.Source = null;

Here’s the resulting UI:


The styles of the current WinUI v2.2 do not apply to ContentDialog yet, that’s why the dialog itself and its buttons have no rounded corners. Don’t worry: this will change in WinUI v2.3.

Let’s sprinkle some Acrylic

These days, fluent apps need a touch of acrylic material. The XamlFlix UI area is almost entirely covered with movie poster images, so we decided to use an AcrylicBrush for the whole background:

    <AcrylicBrush BackgroundSource="HostBackdrop"
                    TintColor="{ThemeResource SystemColorBackgroundColor}"
                    FallbackColor="{ThemeResource ApplicationPageBackgroundThemeBrush}" />

We blended that background into the title bar:

private void ExtendAcrylicIntoTitleBar()
    CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
    ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
    titleBar.ButtonBackgroundColor = Colors.Transparent;
    titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;

In this setting Windows only draws the system buttons, and makes you responsible for displaying the app title. Here’s an appropriate (and reusable) window title declaration:

<TextBlock xmlns:appmodel="using:Windows.ApplicationModel"
            Text="{x:Bind appmodel:Package.Current.DisplayName}"
            Style="{StaticResource CaptionTextBlockStyle}"
            Margin="12 8 0 0" />

The Code

The XamlFlix sample app lives here on GitHub. For more WinUI samples also check the XAML Controls Gallery and the Windows Community Toolkit Sample App in the Store (sources are also on GitHub).

Improving the accessibility of a UWP control

In this article we’ll show some techniques to improve the accessibility of a custom control in UWP. We’ll focus on three aspects:

  • Support for High Contrast themes,
  • Narrator compatibility, and
  • Keyboard input capability.

We’ll use the Radial Gauge control from Windows Community Toolkit as an example – the High Contrast and Narrator code in this article was recently merged into the source.

Supporting High Contrast themes

Adding Theme Dictionaries

With Settings –> Ease of access –> High Contrast, a Windows user can switch his color scheme to a small palette of contrasting colors. There may be medical reasons for this (like cataract or diabetic retinopathy) but it could also be set as to deal with working conditions (like direct sunlight on the screen, or insufficient lighting).

In a UWP app, all of the built-in native controls (the “XAML Common Controls”) respect this user setting and will update their UI. As an app developer you have to make sure

  • not to override that behavior of the native controls that you use, and
  • to provide a similar behavior for the XAML elements that you write yourself: pages and custom controls.

Basically this boils down to never hard coding colors.

When building a custom control, you should create a ThemeDictionary that includes an entry for ‘High Contrast’. Here’s a XAML snippet from the previous style definition from the Radial Gauge control. It came with direct assignment of colors:

<Style TargetType="local:RadialGauge"> 
   <Setter Property="NeedleBrush" 
           Value="{ThemeResource SystemControlBackgroundAccentBrush}" /> 
   <Setter Property="TrailBrush" 
           Value="{ThemeResource SystemControlBackgroundAccentBrush}" />  
   <Setter Property="TickBrush" 
           Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />  
   <Setter Property="ScaleTickBrush" 
           Value="Transparent" /> 
   <!-- ... --/>

The brushes were pulled from theme resources to support Light an Dark themes. That’s a good start, but it doesn’t cover the High Contrast scenario. You should stick to a restricted palette of only 8 system colors in the High Contrast section of the theme dictionary:

Key Initial default
SystemColorButtonFaceColor #FFF0F0F0
SystemColorButtonTextColor #FF000000
SystemColorGrayTextColor #FF6D6D6D
SystemColorHighlightColor #FF3399FF
SystemColorHighlightTextColor #FFFFFFFF
SystemColorHotlightColor #FF0066CC
SystemColorWindowColor #FFFFFFFF
SystemColorWindowTextColor #FF000000

To support High Contrast in the Radial Gauge, an extra layer of abstraction was added in the color brush assignments by means of a resource dictionary:

    <ResourceDictionary x:Key="Default">
        <SolidColorBrush x:Key="RadialGaugeNeedleBrush"
                         Color="{ThemeResource SystemChromeHighColor}" />
        <SolidColorBrush x:Key="RadialGaugeTrailBrush"
                         Color="{ThemeResource SystemChromeHighColor}" />
        <SolidColorBrush x:Key="RadialGaugeScaleBrush"
                         Color="{ThemeResource SystemBaseMediumLowColor}" />
        <SolidColorBrush x:Key="RadialGaugeScaleTickBrush"
                         Color="{ThemeResource SystemBaseMediumLowColor}" />
        <SolidColorBrush x:Key="RadialGaugeTickBrush"
                         Color="{ThemeResource SystemBaseHighColor}" />
        <SolidColorBrush x:Key="RadialGaugeForeground"
                         Color="{ThemeResource SystemBaseHighColor}" />
    <ResourceDictionary x:Key="Light">
        <!-- ... -->
    <ResourceDictionary x:Key="Dark">
        <!-- ... -->
    <ResourceDictionary x:Key="HighContrast">
        <!-- ... -->

The default style of the control was updated to refer to resources from that dictionary:

<Style TargetType="local:RadialGauge">
    <Setter Property="NeedleBrush"
            Value="{ThemeResource RadialGaugeNeedleBrush}" />
    <Setter Property="TrailBrush"
            Value="{ThemeResource RadialGaugeTrailBrush}" />
    <Setter Property="ScaleBrush"
            Value="{ThemeResource RadialGaugeScaleBrush}" />
    <Setter Property="ScaleTickBrush"
            Value="{ThemeResource RadialGaugeScaleTickBrush}" />
    <Setter Property="TickBrush"
            Value="{ThemeResource RadialGaugeTickBrush}" />
    <Setter Property="Foreground"
            Value="{ThemeResource RadialGaugeForeground}" />
    <!-- ... -->

The resource dictionary has an entry for ‘High Contrast’ with only brushes out of the limited set of system colors:

<ResourceDictionary x:Key="HighContrast">
    <SolidColorBrush x:Key="RadialGaugeNeedleBrush"
                     Color="{ThemeResource SystemColorHotlightColor}" />
    <SolidColorBrush x:Key="RadialGaugeTrailBrush"
                     Color="{ThemeResource SystemColorHotlightColor}" />
    <SolidColorBrush x:Key="RadialGaugeScaleBrush"
                     Color="{ThemeResource SystemColorWindowColor}" />
    <SolidColorBrush x:Key="RadialGaugeScaleTickBrush"
                     Color="{ThemeResource SystemColorWindowColor}" />
    <SolidColorBrush x:Key="RadialGaugeTickBrush"
                     Color="{ThemeResource SystemColorWindowTextColor}" />
    <SolidColorBrush x:Key="RadialGaugeForeground"
                     Color="{ThemeResource SystemColorWindowTextColor}" />

The control now supports High contrast themes, and we didn’t even need to change the code behind.

Ignoring local properties

When a developer places our control on a page, he can locally assign brushes to the control’s color settings – after all that’s why we decorated it with properties. It makes sense for the control to ignore these assignments when a High Contrast theme is applied. For that we need to detect whether we’re in High contrast mode or not, and find a way to get notified when the user enables or disables the feature.

This is were the AccessibilitySettings class enters the picture, with a HighContrast property and a HighContrastChanged event. When the app starts, and whenever the event fires, we update the color scheme if necessary. We first create an instance of the class:

private static readonly AccessibilitySettings ThemeListener = new AccessibilitySettings();

And then register an event handler. That handler may force a redraw of the control –to update the colors- so the control’s Visual Tree should be assembled (but not yet displayed) when we register it. That makes the OnApplyTemplate event the best choice to host this code:

ThemeListener.HighContrastChanged += ThemeListener_HighContrastChanged;

Let’s take a look at the code to change the color scheme. When the app starts, we create a cache to remember the local values for the different colors. All the brushes are defined as dependency properties. To detect whether a dependency property is locally overridden (in XAML or C#, but not by a theme dictionary), we can use ReadLocalValue. It returns the local value or the so-called UnSetValue that indicates that no value was assigned:

private SolidColorBrush _needleBrush;
private Brush _trailBrush;
private Brush _scaleBrush;
// More brushes ...
_needleBrush = ReadLocalValue(NeedleBrushProperty) as SolidColorBrush;
_trailBrush = ReadLocalValue(TrailBrushProperty) as SolidColorBrush;
_scaleBrush = ReadLocalValue(ScaleBrushProperty) as SolidColorBrush;
// More assignments ...

When we enter a High Contrast theme, we unbind the local values from the dependency properties so that the entries of the theme dictionary are used. And when we enter a non High Contrast theme, we reassign the local values from the cache to reinstall the original color scheme:

private void OnColorsChanged()
    if (ThemeListener.HighContrast)
        // Apply High Contrast Theme.
        ClearBrush(_needleBrush, NeedleBrushProperty);
        ClearBrush(_trailBrush, TrailBrushProperty);
        ClearBrush(_scaleBrush, ScaleBrushProperty);
        // More of these ...
        // Apply User Defined or Default Theme.
        RestoreBrush(_needleBrush, NeedleBrushProperty);
        RestoreBrush(_trailBrush, TrailBrushProperty);
        RestoreBrush(_scaleBrush, ScaleBrushProperty);
        // More of these ...

    // ...

To clear and restore the brushes, we use ClearValue and SetValue respectively:

private void ClearBrush(Brush brush, DependencyProperty prop)
    if (brush != null)

private void RestoreBrush(Brush source, DependencyProperty prop)
    if (source != null)
        SetValue(prop, source);

For a deeper dive into Dependency Properties, check this documentation.

In the small sample app that I wrote, I encapsulated all accessibility related code behind (there’s more to come further in this article) in a separate partial class file:


To get these file under the xaml.cs file in Visual Studio’s explorer, I tweaked the project file:


That sample app has a page with three radial gauge controls. The one in the middle has a local assignment for some colors:

<controls:RadialGauge Unit="Mississippi"

Here’s how that page looks like in a non High Contrast theme. On the left side of the screen there’s the Settings app; the right side is main page of the sample app:


Here’s the app in High Contrast mode. Observe the limited color palette, and the fact that we successfully ignored the local colors for the middle gauge:


The UI Automation API

Another way to improve the accessibility of a custom UWP control is to provide screen reader support. Narrator lets you use your device to complete common tasks without mouse or touch input. It reads and interacts with elements on the screen, like text and buttons. Of course that only works if you stick to a protocol. That protocol is Microsoft UI Automation, an API in Windows that enables your apps to provide (and consume) programmatic information about its user interface. Providing programmatic access to most UI elements on the desktop enables assistive technology products, such as Narrator and Magnifier, to provide this information to the end users, e.g. by speech.

One of the most important components of Windows Automation is the so-called UI Automation Tree. This is the hierarchical representation of your desktop window, its child elements (open windows) and their UI components (menus, buttons, lists, …). The UI Automation Tree makes a difference between Control elements (interactive) and Content elements, but it makes no difference in technology: it works against all stacks: WinForms, Web, XAML, …

Supporting Narrator

Creating and registering an Automation Peer

An Automation Peer is a class that helps exposing the content of a UI element class to Windows UI Automation. It ensures that the UI Automation Tree does not have to rely on high-level assumptions, so it improves the service of components like Narrator and Magnifier.

To create an automation peer for a class, you just create a descendant from AutomationPeerFrameworkAutomationPeer is a good parent for a XAML control- and specify the described class (the ‘owner’) in the constructor:

public class RadialGaugeAutomationPeer : FrameworkElementAutomationPeer
    public RadialGaugeAutomationPeer(RadialGauge owner)
        : base(owner)
    { }

    // ...

To activate the automation peer, you also have to override the OnCreateAutomationPeer in the owner class (RadialGauge in our case):

protected override AutomationPeer OnCreateAutomationPeer()
    return new RadialGaugeAutomationPeer(this);

Basic overrides

There are two methods that you would probably override in every automation peer. The first one is GetChildrenCore(). It returns the list of child elements that you want to expose to UI Automation. In the case of the RadialGauge, we want to expose the control to as a single element and hide its details. So the override returns no children:

protected override IList<AutomationPeer> GetChildrenCore()
    return null;

The second important automation peer method is GetNameCore() which returns the main description of the component. If you want more than the fully qualified class name, then you should override it. Here’s what we did in the RadialGauge to make it return the class name and unit measure:

protected override string GetNameCore()
    var gauge = (RadialGauge)Owner;
    return "radial gauge. " + (string.IsNullOrWhiteSpace(gauge.Unit) ? "no unit specified. " : "unit " + gauge.Unit + ". ");

Tip: provide punctuation and pauses (blanks) in the result string to create a natural description. When Narrator reads the screen, it respects all of these.

After the name, Narrator tells the type of control. Custom is the default return value for GetAutomationControlTypeCore(), so this is actually an obsolete override:

protected override AutomationControlType GetAutomationControlTypeCore()
    return AutomationControlType.Custom;

I just want to point out that the type comes from the AutomationControlType enumeration. So you can not add your own here, but you can still expose a lot more details of your control.

Refining the Automation Peer

To find out more details about your control, Windows Automation will call GetPatternCore() a few times to see if it supports some protocols. One of these protocols is RangeValue which describes the controls that have a Value that is between a Minimum and a Maximum, controls such as … the RadialGauge.

To fulfill the protocol we have to implement the IRangeValueProvider interface:

public class RadialGaugeAutomationPeer :
    // ...
public double Value => ((RadialGauge)Owner).Value;
public double Minimum => ((RadialGauge)Owner).Minimum;
public double SmallChange => ((RadialGauge)Owner).StepSize;
public bool IsReadOnly => !((RadialGauge)Owner).IsInteractive;
// ...

Then we have to override GetPatternCore() to return a reference for each protocol that we implemented:

protected override object GetPatternCore(PatternInterface patternInterface)
    if (patternInterface == PatternInterface.RangeValue)
        // Expose RangeValue properties.
        return this;

    return base.GetPatternCore(patternInterface);

That’s is! Narrator will now say the description of our control, followed by the ValueRange information (Value, Minimum and Maximum). If you activate Narrator (in Settings) and TAB to the different gauges in the sample app, they will be nicely described. Here’s a –silent- screenshot:


You can use the Inspect tool from the Windows SDK to discover and visualize all the information that Windows Automation is able to extract from your control:


Supporting keyboard input

A lot of users don’t use the mouse or a touch screen to interact with their computer, but only the keyboard. So it makes sense for a UWP control to accept keyboard input when it has the focus. The RadialGauge has a handler for the KeyDown event. Its value can be increased and decreased with the right and left arrow keys respectively. The Control key makes the difference between a large change of 5 units and a small change of 1:

private void RadialGauge_KeyDown(object sender, KeyRoutedEventArgs e)
    var step = 1;
    var ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
    if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
        step = 5;

    if (e.Key == VirtualKey.Left)
        Value = Math.Max(Minimum, Value - step);
        e.Handled = true;

    if (e.Key == VirtualKey.Right)
        Value = Math.Min(Maximum, Value + step);
        e.Handled = true;

This article described three techniques to improve the accessibility of a UWP Custom Control. If you want to know more on this topic, check this excellent starting page on the DevCenter.  You’ll quickly learn that spending some time and effort on accessibility makes your controls and apps better for everyone.

If you want to play with the code, the small sample app with the accessible RadialGauge lives here on GitHub.


Using a TreeView Control for Navigation in UWP

In this article we’ll show how to use a TreeView as the main navigation control in a UWP app. We will stay as close as possible to the Fluent Design principles and other current UI guidelines.

Our first approach was to rely on the NavigationView control, since it comes with a full user experience (navigation, hamburger, page title, secondary commands, responsive and fluent design). Unfortunately it is entirely focused on (read: limited to) a flat list of menu items. So we decided to design and build the entire user experience from scratch.

We admit that we expected to run into issues. None of the native UWP apps that could clearly use treeview based navigation –such as the Mail client and the OneNote app- actually have one. So we were a bit suspicious of the TreeView’s capabilities. Fortunately this was just unfounded fear.

We created a sample app with these main navigation components in a Shell page:

  • a SplitView,
  • a TreeView for primary navigation,
  • a Frame to host the pages on a background with parallax effect,
  • a Hamburger button, and
  • a CommandBar for secondary navigation.

Here’s how that app looks like:

Building the User Experience

Here’s the main XAML content of the Shell page:

<!-- SplitView -->
<SplitView x:Name="ShellSplitView">
        <Grid x:Name="SplitViewPane">
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
            <!-- Navigation Tree -->
            <TreeView x:Name="NavigationTree"
                        Style="{StaticResource TreeViewStyle1}" />
            <!-- Command Bar -->
                <!-- AppBarButtons -->
            <!-- Does not seem to work. -->
            <ParallaxView Source="{Binding ElementName=NavigationTree}"
                <!-- Background Image -->

            <!-- Navigation Frame -->
            <Frame x:Name="SplitViewFrame"

<!-- Title Bar -->
<TextBlock x:Name="AppTitle" />

<!-- Hamburger Button -->
<Button x:Name="HamburgerButton">
    <!-- ... -->


We used a classic SplitView control to host the main components: the TreeView on the left and a Frame to hold the current page on the right. The SplitView Pane can be opened or closed with a Hamburger button that sits on top of it (z-index wise).

A SplitView supports four display modes for the Pane, but the NavigationView only uses three display modes for the menu:

  • Minimal: panel shows if needed and on top of content,
  • Compact: panel shows a narrow band of icons, and
  • Expanded: panel shows alongside the content.

We didn’t use icons in the TreeView’s ItemTemplate – and it would anyway be impossible to  to show a multi-level tree in a narrow vertical band. So we decided to skip compact mode in the visual states. As a result the SplitView Pane has always the same width (when visible). It will just toggle between Inline and Expanded according to the app’s width.

Following the guidelines for Acrylic, we made the navigation pane background

  • 60% in-app acrylic in overlay mode, and
  • 60% background acrylic in side-by-side mode.

When using acrylic brushes in your app, don’t forget to provide a fallback color. It’s the solid color that is shown when the composition brushes are not used – i.e. when the app loses focus, or when the user settings or the machine hardware prevent it. Here’s a screenshot of the app when it does not have the focus:


Here’s the definition of the corresponding brushes:

<!-- Splitview Pane -->
<AcrylicBrush x:Key="SplitViewInlineBackgroundBrush"
                FallbackColor="#ffe6ff" />
<AcrylicBrush x:Key="SplitViewOverlayBackgroundBrush"
                FallbackColor="#ffe6ff" />

And here’s how they are declaratively applied in the Visual State Manager:

<!-- VisualState to be triggered when window width is >=1007 effective pixels -->
<VisualState x:Name="Expanded">
        <AdaptiveTrigger MinWindowWidth="1007" />
        <!-- SplitView pane shows as overlay -->
        <Setter Target="ShellSplitView.DisplayMode"
                Value="Inline" />
        <Setter Target="ShellSplitView.PaneBackground"
                Value="{StaticResource SplitViewInlineBackgroundBrush}" />

The Shell page -including the SplitView and its content- is blended into the title area:

// Blends the app into the title bar.
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
titleBar.ButtonForegroundColor = (Color)Application.Current.Resources["TitlebarButtonForegroundColor"];

For more info on this code and its consequences, check the TitleBar Customization documentation.


The TreeView control is the obvious candidate for displaying a hierarchical menu. It is also one of the UWP controls that comes with built-in Reveal highlight effect, a lighting effect that highlights interactive elements, such as command bar buttons, listview items, or treeview nodes when the user moves the pointer near them. Check the bottom left part of the first screenshot in this article for an impression.

We tweaked the TreeViewItem style a little bit to decorate the selected node with a thin vertical bar, just like the NavigationView does (but without an animation). Here’s what we changed :

<!-- Added -->
<Grid x:Name="SelectionGrid"
        HorizontalAlignment="Left" />

<VisualState x:Name="Selected">
        <!-- Changed -->
        <Setter Target="SelectionGrid.Background"
                Value="{ThemeResource TreeViewItemBackgroundSelected}" />
        <Setter Target="ContentPresenter.Foreground"
                Value="{ThemeResource TreeViewItemForegroundSelected}" />
        <Setter Target="ContentPresenterGrid.BorderBrush"
                Value="{ThemeResource TreeViewItemBorderBrushSelected}" />

As part of the process, we also changed the different accent colors so that we don’t rely on the user’s personal accent color:

            <!-- AccentColor overrides -->
            <!-- Shades of OrangeRed -->
            <ResourceDictionary x:Key="Default">
                <Color x:Key="SystemAccentColor">#ff4500</Color>
                <Color x:Key="SystemAccentColorLight1">#ff4500</Color>
                <Color x:Key="SystemAccentColorLight2">#ff8f66</Color>
                <Color x:Key="SystemAccentColorLight3">#b33000</Color>
                <Color x:Key="SystemAccentColorDark1">#ff4500</Color>
                <Color x:Key="SystemAccentColorDark2">#ff8f66</Color>
                <Color x:Key="SystemAccentColorDark3">#b33000</Color>
            <!-- ... -->

Here’s how all of this looks like – before and after the template and color changes:


Notice that we also moved the whole TreeView control some pixels to the left, to vertically align the chevron icons with the Hamburger button.

Hamburger button

We decided to give the Hamburger button the same size and padding as the system buttons (minimize, maximize, and close) and place it into the title bar in the top left corner. If you place input controls in the title bar, then you should override the default interactive part of the title bar (the part that responds to dragging and double clicking) – otherwise your control will not be reachable.

Here’s the XAML for the top left corner:

<!-- Hamburger Button -->
<Button x:Name="HamburgerButton"
        <!-- ... -->

<!-- Title Bar -->
<Grid x:Name="AppTitleBar"
    <TextBlock x:Name="AppTitle"
                Text="{x:Bind appmodel:Package.Current.DisplayName}"
                Style="{StaticResource CaptionTextBlockStyle}"
                Margin="48 8 0 0" />

Here’s how the default title bar zone is overridden:


The code behind the Hamburger button is straightforward. It just needs to toggle IsPaneOpen on the SplitView:

/// <summary>
/// Toggles the SplitView pane.
/// </summary>
private void HamburgerButton_Click(object sender, RoutedEventArgs e)
    ShellSplitView.IsPaneOpen = !ShellSplitView.IsPaneOpen;

Secondary commands

For the secondary commands at the bottom of the navigation panel, we opted for a CommandBar with regular app bar buttons. It’s one of the controls that comes with the Reveal effect built in, and it has the correct size. We considered buttons of the same dimensions as the Hamburger and the system buttons, but this size is to small for buttons that are used often and that have more complex icons.


Our focus of the sample app was mainly on the user experience, so we kept the functional part -the navigation itself- as simple as possible. All the related code is placed directly in the Shell page, albeit in a partial class file. In a real-world app you would build a Navigation Service and then find and call it using singletons, dependency injection, service locator, or any other kind of blood magic. For more info, please check my older blog post on SplitView navigation.

To separate at least some of the concerns, we did create a NavigationMenuItem class that allows to define a hierarchic navigation structure (with the destination page type and parameter, and a Children collection):

Here’s a part of the logical navigation menu in the sample app:

private ObservableCollection<NavigationMenuItem> MainMenu => 
    new ObservableCollection<NavigationMenuItem>
            new NavigationMenuItem
                Text = "Edged Weapons",
                NavigationDestination = typeof(BladesPage),
                Children = new ObservableCollection<MenuItem>
                    new NavigationMenuItem
                        Text = "Arakh",
                        NavigationDestination = typeof(BladesPage),
                        NavigationParameter = "Arakh"
                    new NavigationMenuItem
                        Text = "Dragonglass",
                        NavigationDestination = typeof(BladesPage),
                        NavigationParameter = "Dragonglass"
                    // ...

The Navigate method uses this information to … well … navigate:

/// <summary>
/// Navigates to the specified source page type.
/// </summary>
public bool Navigate(Type sourcePageType, object parameter = null)
    return SplitViewFrame.Navigate(sourcePageType, parameter);

When the app starts up, TreeView nodes are created from the menu structure – with a little help from a recursive extension method:

internal static TreeViewNode AsTreeViewNode(this NavigationMenuItem menuItem)
    var result = new TreeViewNode
        Content = menuItem

    foreach (NavigationMenuItem subItem in menuItem.Children)

    return result;
/// <summary>
/// Populates the TreeView from the Menu.
/// </summary>
private void PopulateTreeView()
    // Populate the tree.
    foreach (var item in MainMenu)

Each node in the TreeView now has a NavigationMenuItem as its Content, so it knows which page to load and with which parameter. Here’s what happens when a node is clicked:

/// <summary>
/// Navigates to the corresponding treeview selection.
/// </summary>
private void TreeView_ItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args)
    if (args.InvokedItem is TreeViewNode node)
        if (node.Content is NavigationMenuItem menuItem)
            var target = menuItem.NavigationDestination;
            if (target != null)
                Navigate(menuItem.NavigationDestination, menuItem.NavigationParameter);

The secondary command buttons call the same method, but without a parameter:

private void SettingsButton_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)

Just to prove that the parameter from the NavigationMenuItem is correctly passed to the Page, here’s how the different pages in the sample app update their subtitle in the top right corner:

protected override void OnNavigatedTo(NavigationEventArgs e)
    if (e.Parameter != null)
        SubTitle.Text = e.Parameter.ToString();


The Back Button

The hierarchical menu on the left -together with the secondary commands at the bottom- give the user immediate access to any page in the app. So personally we’re not in favor of providing a back button. But just for the sake of completeness, we also implemented it.

This implies a method to navigate back:

/// <summary>
/// Returns to the previous page.
/// </summary>
public void GoBack()
    if (SplitViewFrame.CanGoBack)

And you also need to make the system button visible:

/// <summary>
/// Shows the system back button.
/// </summary>
public void EnableBackButton()
    var navManager = SystemNavigationManager.GetForCurrentView();
    navManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    navManager.BackRequested -= (s, e) => GoBack();
    navManager.BackRequested += (s, e) => GoBack();

We placed the Hamburger button in the top left corner. When the system back button (dis)appears, we need to shift that button together with the text block holding the app title:

// Update the title bar when the back button (dis)appears or resizes.
Window.Current.CoreWindow.SizeChanged += (s, e) => UpdateAppTitle();
coreTitleBar.LayoutMetricsChanged += (s, e) => UpdateAppTitle();
/// <summary>
/// Updates the title bar when the back button (dis)appears or resizes.
/// </summary>
private void UpdateAppTitle()
    var full = (ApplicationView.GetForCurrentView().IsFullScreenMode);
    var left = (full ? 0 : CoreApplication.GetCurrentView().TitleBar.SystemOverlayLeftInset);
    HamburgerButton.Margin = new Thickness(left, 0, 0, 0);
    AppTitle.Margin = new Thickness(left + HamburgerButton.Width + 12, 8, 0, 0);

We also added the code to unselect the current TreeView node when the Back or a secondary command button is pressed. Since we weren’t successful in programmatically selecting and unselecting nodes, we applied the old trick of toggling the SelectionMode:

/// <summary>
/// Makes the TreeView lose its selection when there is no corresponding main menu item.
/// </summary>
/// <remarks>This works, but I don't know why...</remarks>
private void SplitViewFrame_OnNavigated(object sender, NavigationEventArgs e)
    NavigationTree.SelectionMode = TreeViewSelectionMode.None;
    NavigationTree.SelectionMode = TreeViewSelectionMode.Single;

We assumed it would be necessary to add some extra code to determine whether the navigation was triggered by the TreeView or not, before deciding to unselect the current node. It turns out that unconditionally toggling the selection mode seems to do the job already. But honestly: this feels like a coincidence.

NavigationTreeView, first of his name ?

We just created a great looking fluent design compatible TreeView based navigation UI. The development was easier than we expected, and the results look better than we expected. Some of you may be tempted to componentize all of this into a user experience just like the current NavigationView control. We think that this can be done with not too much extra effort, but personally we prefer the more granular control that we have in the sample app.

That sample app lives here on GitHub.


An Extended Splash Screen with Lottie Animations in UWP

In this article we demonstrate how to use Lottie animations in the extended splash screen of a UWP application. A Lottie animation is a programmable animated graphic that can be rendered into your XAML.

Here’s how the companion sample app starts up, with its splash screen transitioning into an look-alike page that displays an animation, whilst executing some longer-running code:


Creating an extended splash screen

Sometimes an app needs to execute some longer-running code on startup. Especially the very first time after an install or an upgrade, you may want to connect to the backend, create a user profile, populate a local SQLite database, and defeat the Klingons, the Sith and/or the Daleks.

The long-running code in my sample app is less ambitious:

await Task.Delay(10000);

It is common to handle this scenario with a so-called Extended Splash Screen. This is a page that looks like the native splash screen and that executes the longer-running code, before eventually navigating to the main page. Typically an extended splash screen is decorated with a progress ring to indicate that the app does not hang.

The nice official documentation for creating an extended the splash screen is right here. I started with a copy of the sample code from there, and replaced the progress ring by a Lottie animation.

In a nutshell, here’s the routine to create an extended splash screen:

  • get the position of the SplashScreen image from the LaunchActivatedEventArgs,
  • navigate to an extended splash screen page that displays the same image at the same location,
  • execute the long running code in the Dismissed event handler of the original splash screen, and finally
  • navigate to the ‘real’ homepage or shell.

Adding Lottie capabilities

Lottie is a library to render animations. It uses JSON files that were generated by the Bodymovin extension of Adobe After Effects, a Special Effects editor to create picture and SVG animations. Lottie has implementations for iOS, Android, and the Web (React Native). It is supported by a broad community and has won a number of awards as design and development tool. It seems fair to assume that Lottie is becoming one of the standards for stand-alone animations in apps.

For Native Windows developers, Lottie is now available as LottieUWP, a NuGet package written by Alexandre Chohfi. To look it up from Visual Studio, you need to check the ‘Include prerelease’ box in NuGet Package Manager:


Adding Lottie files

LottieFiles is a great resource to get some free JSON files to experiment with:


That’s where I found the beer bubbles animation.

Add the downloaded JSON file(s) to your project, and don’t forget to change their Build Action to Content:


Displaying Lottie animations

The best way to get some insight into LottieUWP and its API is viewing this #ifdef episode on Channel 9. For the sample app, I just added a LottieAnimationView in the extended splash screen, with an auto-played, infinite-looping animation, nicely positioned over the beer glass background:

That’s all that’s needed to host and run the animation. I just modified the Speed – programmatically, since assigning a value declaratively in XAML is not very well supported in the current LottieUWP version (after all it *is* a pre-release):

// Adjust the speed of the Lottie animation.
SplashScreenAnimation.Speed = 3;

The end-user may resize the window or rotate his device when the app is starting. So when the background image is repositioned we also have to update the size and location of the LottieAnimationView:

// Position the extended splash screen image in the same location as the system splash screen image.
private void PositionImage()
    extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
    extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
    extendedSplashImage.Height = splashImageRect.Height;
    extendedSplashImage.Width = splashImageRect.Width;

    // Position the Lottie animation.
    var factor = splashImageRect.Width / 620;
    SplashScreenAnimation.SetValue(Canvas.LeftProperty, splashImageRect.X + 100 * factor);
    SplashScreenAnimation.SetValue(Canvas.TopProperty, splashImageRect.Y + 150 * factor);
    SplashScreenAnimation.Width = 180 * factor;

Tweaking the JSON files

Visual Studio allows you to unminify the JSON file, this will reveal a structure of layers with the strokes and shapes and their use in animations and transformations. I assume that it’s unlikely that we’re going to apply changes manually in there. Nevertheless there are some ways to slightly tweak the files.

In LottieFile’s preview page you can visualize the selected JSON against different background colors. This helps you to reveal the color scheme that is used in the animation. Here you can see that the filter animation uses plain white to fill the circles – so they’re not transparent:


The button in the top right corner launches the Lottie Editor:


This page allows you to change the color of some elements. The corresponding changes to the JSON files are logged in the browser’s Console.

Other use cases

The main page of the sample app shows how to decorate a button with a (more or less) subtle animation to draw the user’s attention. This is how it looks like:


Please note that the animated GIF on this page loops infinitely, unlike the animation in the UWP app.

Again, we used a LottieAnimationView, but we set the RepeatCount to 2 and the RepeatMode to Reverse to obtain a brief symmetric animation:

And again, we adjusted the speed programmatically:

// Adjust the speed of the animation.
// Does not work declaratively for now.
MainpageAnimation.Speed = 3F;

Use PlayAnimation to (re)play the Lottie animation:

// Replay the animation.

I just added this call to verify whether the button is still clickable when the animation is running on top of it. Fortunately this is the case.

if you want see more Lottie API examples, please check Corrado’s blog post on the subject.

GitHub Repo N° 50

The sample app lives here on GitHub in my 50th public repo.


A Fluent Button Flyout for UWP

In this article we describe how to build an elegantly designed and animated fluent ToggleButton-Popup combination for use in UWP apps as an alternative for the less fluent Button Flyout. The code is not mine, I merely reused code and components from the Continuity framework by Justin Liu. This frameworks contains a lot of helpers for implementing Fluent Design in your apps without needing Windows 10 Fall Creators Update.

The ToggleButton-Popup combo is an excellent widget to display extra information such as a help text.

Here’s how all of this may look like (styling is up to you of course). It starts with a stand-alone round ‘more’ button, with hover animations. When pressed, the button rotates toward the opening flyout, while changing its shape to look like a ‘close’ button that becomes connected to the content that was just revealed. In the mean time, the flyout itself opens with a scale animation as if it grew out of the button:


Closing the button and dismissing the flyout come with reverse animations.

I’ve been looking for ways to animate opening and closing Flyout or ContentDialog instances. I went through many of the XAML animations techniques, but could not find a way. Flyout and ContentDialog don’t come with Visual States, so Visual Transitions are not an option. Although its name seems promising, PopInThemeAnimation is not applicable. And if it were, it doesn’t come with a scale animation (only opacity and translation).

I almost gave up, and tried to to accept that flyouts would always open and close like this:


Frankly, I don’t like the animations. But what’s worse: you can not even see which of the buttons was actually pressed…

Then I came across this sample Kliva design with exactly the user experience I was looking for:


I decided to copy the relevant code into my own solution under Features/Continuity to get some Fluent-As-A-Service:


The Kliva demo is not using a Button with its Flyout, but a ToggleButton with ‘just’ a Grid. My only mission was to replace the Grid with a Popup. After a few iterations, I came up with the following setup, which even allows the Popup to have IsLightDismissEnabled on.:

  • A toggle button with storyboarded animations is placed in a container
  • A Popup is placed next to it with
  • The content of the Popup (not the Popup itself) is given implicit Show and Hide Composition API animations.

Here’s the corresponding XAML definition:

<!-- Toggle Button -->
<continuity:CircularToggleButton x:Name="TheToggle"
                                    CheckedBackground="{StaticResource HighlightBrush}"
                                    CheckedCornerRadius="6 0 0 6"
                                    FontFamily="Segoe UI">
        <ContentControl Margin="3"
                        Style="{StaticResource IconCloseStyle}" />
    <ContentControl Style="{StaticResource IconMoreStyle}" />
<!-- 'Flyout' -->
<Popup x:Name="ThePopup"
        IsOpen="{Binding IsChecked, ElementName=TheToggle, Mode=TwoWay}"
        HorizontalOffset="{Binding ActualWidth, ElementName=TheToggle}"
    <Grid x:Name="TheGrid"
            Visibility="{Binding IsOpen, ElementName=ThePopup}">
        <!-- Content -->

That’s it! Let’s dive into some details.

An animated circular toggle button

The CircularToggleButton adds a few dependency properties to ToggleButton, like content, background color and corner radius for the different states:

public sealed class CircularToggleButton : ToggleButton
    public static readonly DependencyProperty CheckedContentProperty =
            new PropertyMetadata(null));

    public object CheckedContent
        get => GetValue(CheckedContentProperty);
        set => SetValue(CheckedContentProperty, value);

    // ..

It also comes with a circular custom style and some nice visual effects and animations.

Here’s how the PointerOver VisualState pumps up the size of the content using a RenderTransform with a CompositeTransform on ScaleX and ScaleY:

<VisualState x:Name="PointerOver">
        <Setter Target="CheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
                Value="1.1" />
        <Setter Target="CheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
                Value="1.1" />
        <Setter Target="UncheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
                Value="1.1" />
        <Setter Target="UncheckedContentPresenter.(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
                Value="1.1" />
        <Setter Target="BackgroundVisual.Opacity"
                Value="0.9" />

Here’s the VisualTransition with the StoryBoard on CornerRadius that turns the round button into its ‘connected’ shape when checked:

<VisualTransition GeneratedDuration="0:0:0.25"
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.CornerRadius)"
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="{Binding CheckedCornerRadius, RelativeSource={RelativeSource TemplatedParent}}" />

If you want to know more about storyboarded animations, this circular toggle button style definition is a nice tutorial. Storyboarded animations are a way to change a dependency property over time. When there’s a visual impact of this, the animation may or may not require the UI thread. While the SDK’s evolve, more and more of these animations are internally rewritten to run on the composition thread. So there’s no need for you give up readable declarative Storyboards in XAML in favor of dark imperative code against the Composition API. But for the second part of this article, we’ll use the latter…

An animated Popup

The Popup control is a XAML container that allows you to place content on top of other content. You can not animate the Popup itself but fortunately you can animate its content. As promised we’ll use Composition animations for this. These are 60-frames-per-second animations that run independent of the UI thread. They’re a bit harder to write, but there are a lot of helpers available, like these from UWP Community Toolkit.

Here’s the Continuity helper that starts it all:

    centerPoint: new Vector3(0.0f, 40.0f, 0.0f), 
    showFromScale: 0.2f, 
    hideToScale: 0.2f, 
    showDuration: 400, 
    hideDuration: 400);

Here’s part of its implementation.

A time based Composition API animation of the type Vector2KeyFrameAnimation is created with the Scale of the Visual as Target:

if (!showFromScale.Equals(1.0f))
    showeScaleAnimation = compositor.CreateVector2KeyFrameAnimation();
    showeScaleAnimation.InsertKeyFrame(0.0f, new Vector2(showFromScale));
    showeScaleAnimation.InsertKeyFrame(1.0f, Vector2.One);
    showeScaleAnimation.Duration = TimeSpan.FromMilliseconds(showDuration);
    showeScaleAnimation.DelayTime = TimeSpan.FromMilliseconds(showDelay);
    showeScaleAnimation.Target = "Scale.XY";

The different animations (scale, position, opacity, …) are placed together in an AnimationGroup (one for hide and one for show):

var showAnimationGroup = compositor.CreateAnimationGroup();
// ...
if (showeScaleAnimation != null)

These animation groups are then implicitly hooked to the Popup’s content, using SetImplicitShowAnimation and SetImplicitHideAnimation:

ElementCompositionPreview.SetImplicitShowAnimation(element, showAnimationGroup);

Under the hood, a lot of different animation techniques were used to create this user experience, but I love the result! And while it’s probably possible to forge this into a single custom control, I’m not sure if it would add much value….

The code

The ‘fluent button flyout’ sample lives here on Github, the inspiring Continuity by Justin Liu is right here.


How to generate an Adobe Color Swatch and transform it to XAML brushes

There are a lot of good free web sites that can create a group of matching colors for you. While it’s nice to go online and create such a palette, it’s another thing to transform a –sometimes lengthy- list of colors on an HTML page into something that can be used in XAML, e.g. a list of brush definitions.

Luckily, most of these web sites have one thing in common: they allow you to export the color palette to a so-called Color Swatch. That’s an Adobe Photoshop file format for storing a list of named colors. Photoshop uses the .aco extension for this file type.

In this blog post, I’ll introduce you to some of these web sites, and I also present a Portable Class Library project together with a Universal Windows Platform app to read a Color Swatch, and export its content to a list of XAML SolidColorBrush definitions that you can use as a resource.

How to create a color palette

Here are some approaches that you can take to come up with a consistent color palette for your app.

The mathematical approach

In the mathematical approach, you hand pick one or two primary colors and calculate the rest of the palette. This calculation is based on the position of the colors in a color wheel. The generated theme will contain your selected base colors, plus their adjacent (a.k.a. analog or harmonious) colors or triad colors or tetrad colors, and optionally their complementary color.

There are a lot of web sites with an interactive color wheel, such as Adobe itself and ColorsOnTheWeb, but I always keep coming back to Paletton:


Not only does this site allow you to interactively design a color palette, it also has a lot of preview options: site samples, drawings, and even animations. It also allows you to export the color scheme to different formats, including XML, CSS, and ACO:


There is a lot more in color theory and color psychology than just the color wheel: warmth, shades, tints, hue, and so on. But unless you are a talented designer, a color palette based on the color wheel will have better harmony and contrast (and hence will be better perceived by your users) than a random set of hand picked colors.

The image approach

A second approach for generating a color scheme is analyzing the pixels of an image that you find attractive. There a a lot of web sites around that create a color palette out of an image that you upload.

Here’s an example of a palette that was generated from the picture of a fox, by Pictaculous:


The site not only returns the colors of the calculated palette, but also links to related color schemes that are stored in the libraries of Adobe Kuler and ColourLovers. There’s also an API for all of this. The export format for Pictaculous is … Adobe Photoshop Color Swatch.

Every site or tool uses a different algorithm to pick scheme colors, so you may want to shop around. Here’s what Adobe –my favorite site for this approach- generates from that same fox:


With the image-to-palette approach you rely on the inherent beauty and harmony of nature. Well … more probably you rely on the talent of a photographer, artist, fashion designer, or film maker. When they create an image, they do that with a color palette in mind. That palette is based on … the color wheel. Here’s a nice introduction to cinematic color design, and there are more examples at MoviesInColor (which unfortunately has no export feature).

By the way, it’s not only photos from nature that yield nice color palettes. Here’s what CSSDrive generates from a photo of a city:


Themes that are generated by CSS Drive can be saved as CSS or ACO.

Hint: if you’re looking for candidate pictures for this approach, any Bing background will do:


Get a designer

Of course you can also get a professional graphic designer to create a color palette for you. The odds are very high that he or she will come up with an Adobe Color Swatch. That’s also what Google’s Material Design’s designers have done: you can download all of their color palettes right here. It should be no surprise that this is … an .aco file.

Reading an Adobe Color Swatch file

I was getting tired of copy-pasting individual hexadecimal color codes out of HTML, and into XAML. So I was pleased to discover that they all support the .aco format. The next step was building a Universal Windows Platform app to transform the list of named colors in a Color Swatch into a list of XAML SolidColorBrush definitions.

The C# code that reads the color swatch content is written by Richard Moss, and described in this excellent article. I just copy-pasted the algorithm out of its Windows Forms application into a stand-alone Portable Class Library. So it can be called now from any .NET environment, including Xamarin. I removed the references to File and Color from the original code (they don’t exist in PCL), and stored the algorithm in its own class.

The AcoConverter class has only one public method –ReadPhotoShopSwatchFile– that takes a stream –the content of the .aco file- and returns a collection of SwatchColor – a small helper class.


I also created an UWP app that lets you select a Color Swatch through a FileOpenPicker, visualize the palette, and export it to a list of XAML SolidColorBrush definitions through a FileSavePicker.

Here’s a palette from Paletton:


This is how that palette looks like in the app:


And here’s the export:

<SolidColorBrush x:Key='Primary color 1' Color='#FFAA3939' /> 
<SolidColorBrush x:Key='Primary color 2' Color='#FFFF5555' /> 
<SolidColorBrush x:Key='Primary color 3' Color='#FFF35151' /> 
<SolidColorBrush x:Key='Primary color 4' Color='#FF612020' /> 
<SolidColorBrush x:Key='Primary color 5' Color='#FF180808' /> 
<SolidColorBrush x:Key='Secondary color (1) 1' Color='#FF226666' /> 
<SolidColorBrush x:Key='Secondary color (1) 2' Color='#FF4BE2E2' /> 
<SolidColorBrush x:Key='Secondary color (1) 3' Color='#FF319292' /> 
<SolidColorBrush x:Key='Secondary color (1) 4' Color='#FF133A3A' /> 
<SolidColorBrush x:Key='Secondary color (1) 5' Color='#FF050E0E' /> 
<SolidColorBrush x:Key='Secondary color (2) 1' Color='#FF7B9F35' /> 
<SolidColorBrush x:Key='Secondary color (2) 2' Color='#FFC3FA53' /> 
<SolidColorBrush x:Key='Secondary color (2) 3' Color='#FFB0E34C' /> 
<SolidColorBrush x:Key='Secondary color (2) 4' Color='#FF465A1E' /> 
<SolidColorBrush x:Key='Secondary color (2) 5' Color='#FF111607' />

Source code

The source code lives here on GitHub. As already mentioned, the core logic is in a PCL project, so it can be called from any .NET environment.