Edit

Share via


Keyboard API and events parity between UWP and WinUI 3

The migration of apps from the Universal Windows Platform (UWP) to the Windows App SDK (specifically, WinUI 3) might require a few changes in the way input keyboard events are handled, primarily due to the app model differences. This topic describes commonly identified differences.

By using UIElement-specific WinUI 3 event handlers, and developing custom solutions for event routing, you can easily transition your apps to modern Windows applications.

Mapping to WinUI 3 APIs from UWP APIs

UWP APIs

In UWP, CoreWindow serves as the fundamental component attached directly to each application window, handling global input events across the application. In this topic, some of the commonly used events in conjunction with CoreWindow are discussed:

  • KeyDown. Event raised by any key press when the app window has focus.
  • KeyUp. Event raised when any key is released.
  • CharacterReceived. Event raised when a new character is received by the input queue.
  • CoreDispatcher.AcceleratorKeyActivated. Event raised when an accelerator key is activated (either pressed or held down).
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        var coreWindow = CoreWindow.GetForCurrentThread();
        coreWindow.KeyDown += CoreWindow_KeyDown;
        coreWindow.KeyUp += CoreWindow_KeyUp;
        coreWindow.CharacterReceived += CoreWindow_CharacterReceived;
        coreWindow.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
    }

    private void CoreWindow_KeyDown(CoreWindow sender, KeyEventArgs args)
    {
        System.Diagnostics.Debug.WriteLine($"KeyDown: {args.VirtualKey}");
    }
    private void CoreWindow_KeyUp(CoreWindow sender, KeyEventArgs args)
    {
        System.Diagnostics.Debug.WriteLine($"KeyUp: {args.VirtualKey}");
    }

    private void CoreWindow_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args)
    {
        System.Diagnostics.Debug.WriteLine($"CharacterReceived: {(char)args.KeyCode}");
    }

    private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
    {
        if (args.EventType == CoreAcceleratorKeyEventType.KeyDown)
        {
            bool isCtrlPressed = (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) & CoreVirtualKeyStates.Down) ==
            CoreVirtualKeyStates.Down;
            if (isCtrlPressed && args.VirtualKey == VirtualKey.C)
            {
                System.Diagnostics.Debug.WriteLine("Ctrl+C Pressed");
            }
            else if (args.VirtualKey == VirtualKey.F1)
            {
                System.Diagnostics.Debug.WriteLine("F1 Key Pressed");
            }
        }
    }
}

WinUI 3 APIs (Windows App SDK)

WinUI 3 (Windows App SDK) has a different concept from CoreWindow. Instead, WinUI 3 provides an input event handling mechanism using Microsoft.Ui.Xaml.UIElement (UIElement). Each class that inherits from UIElement can implement various keyboard or pointer events (which are also present in UWP's CoreWindow) such as KeyUp, KeyDown, CharacterReceived, and others. This approach allows event handling at the level of a specific UI control.

For detailed info about event handling, see Keyboard events. You can associate keyboard events either XAML or in imperative source code. These examples demonstrate key event handling through code and accelerator key events in XAML.

<Window
    x:Class="SampleApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SampleApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Orientation="Horizontal" x:Name="stackPanelControl" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button x:Name="myButton" Click="myButton_Click">Click Me</Button>
        <StackPanel.KeyboardAccelerators>
            <KeyboardAccelerator Key="C" Modifiers="Control" Invoked="OnCtrlCInvoked"/>
        </StackPanel.KeyboardAccelerators>
    </StackPanel>
</Window>
public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
        stackPanelControl.KeyDown += OnKeyDownHandler;
        stackPanelControl.KeyUp += OnKeyUpHandler;
        stackPanelControl.CharacterReceived += OnCharacterReceivedHandler;
    }

    private void myButton_Click(object sender, RoutedEventArgs e)
    {
        myButton.Content = "Clicked";
    }

    private void OnKeyDownHandler(object sender, KeyRoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine($"KeyDown: {e.Key}");
    }

    private void OnKeyUpHandler(object sender, KeyRoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine($"KeyUp: {e.Key}");
    }

    private void OnCharacterReceivedHandler(UIElement sender, CharacterReceivedRoutedEventArgs args)
    {
        System.Diagnostics.Debug.WriteLine($"CharacterReceived: {(char)args.Character}");
    }

    private void OnCtrlCInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
    {
        if (args.KeyboardAccelerator.Key == VirtualKey.C && args.KeyboardAccelerator.Modifiers == VirtualKeyModifiers.Control)
        {
            System.Diagnostics.Debug.WriteLine("Ctrl+C Pressed");
            args.Handled = true;
        }
    }
}

UWP sample apps for keyboard events

WinUI 3 sample apps for keyboard events and KeyboardAccelerator

See also

UWP APIs

WinUI 3 APIs (Windows App SDK)