Styling Controls for Windows Apps

One of the things that we take for granted when using applications that have been designed for Windows is the subtle cues that exist for when you’re using the mouse and/or keyboards. For example when you mouse over a button, or an item in a list, the background color changes slightly. Similarly when you use Tab to navigate focus around an application, elements change color, or have a focus border, to indicate what element is in focus. In this post we’re going to look at a couple of these cues that exist in both UWP and WinUI (and of course the Uno Platform) and how they compare to what’s being delivered as part of .NET Maui.

The changing of background color, or displaying of a border, when the mouse moves over an element, or when an element gets focus, represents changing the visual state of the element. Not surprising, on Windows (both UWP and WinUI) this is represented by the different visual states of an element.

Let’s take the Button control as an example, if we look at the default style fo the WinUI Button, you can see that it has a few visual states defined (I’ve excluded a lot of the XAML for brevity). Here we can see that there are different visual states for when the Button is Pressed and when the mouse moves over the control (PointerOver).

<Style TargetType="Button">
    ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ContentPresenter x:Name="ContentPresenter" ... >
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" ... />
                            <VisualState x:Name="PointerOver">
                            <VisualState x:Name="Pressed">
                            <VisualState x:Name="Disabled">
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </ContentPresenter>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

However, what is missing is what happens when the Button gets focus? It would appear that this isn’t handled, except if you try out a WinUI application and Tab between the controls, you can see a border appear around the Button. It turns out that focus is handled automatically by the design system – this can be disabled using the UseSystemFocusVisuals bool property. If you disable this property, you can specify your own set of focus visual states:

<VisualStateGroup x:Name="FocusStates">
    <VisualState x:Name="Focused">
        <VisualState.Setters>
            <Setter Target="ContentPresenter.Background"
                    Value="Green" />
        </VisualState.Setters>
    </VisualState>
    <VisualState x:Name="Unfocused" />
    <VisualState x:Name="PointerFocused" />
</VisualStateGroup>

So, this is what you get out of the box with UWP and WinUI, so you’d expect that .NET Maui would handle support for mouse and keyboard using the built in control support. However, this is not the case – creating a new .NET Maui application you get a basic page with a Button that increments a counter. There’s no pointer or pressed state for the button. However, if you press Tab you do get the system visuals, which in the case of a Button is a border, indicating it’s in focus.

Given the heritage of Xamarin.Forms being a mobile-first framework, it doesn’t surprise me that .NET Maui doesn’t handle keyboard and mouse states correctly. However, with Windows being a key platform for .NET Maui, it’s concerning that basic platform features aren’t being leveraged.