Responding to keyboard interactions (Windows Store apps using C#/VB/C++ and XAML)

Language: JavaScript and HTML | VB/C#/C++ and XAML
2 out of 19 rated this helpful - Rate this topic

You can respond to keystroke actions from a hardware or touch keyboard in your Windows Store apps built for Windows using C++, C#, or Visual Basic. To do this, use the keyboard events that are available in Windows 8.

Keyboard support is important for accessibility, and to enable functionality when a touch screen isn't present. Additionally, keyboard support can make your app more usable for frequent keyboard users. Users should be able to navigate your app by using Tab and arrow keys, activate UI elements by using Spacebar and Enter, and access commands by using keyboard shortcuts.

See Displaying and editing text for more info on text input.

Roadmap: How does this topic relate to others? See:

Keyboard events

Windows Store apps using C++, C#, or Visual Basic provide the following keyboard events, which can occur for both hardware and touch keyboards.

EventDescription
KeyDown Occurs when a key is pressed.
KeyUp Occurs when a key is released.

 

Keyboard events and focus

Controls in your UI generate keyboard events only when they have input focus. An individual control gains focus when the user clicks or taps directly on that control in the layout, or uses the Tab key to step into a tab sequence within the content area.

You can also call a control's Focus method to force focus. This is necessary when you implement shortcut keys, because keyboard focus is not set by default when your UI loads. For more info, see the Shortcut keys example later in this topic.

For a control to receive input focus, it must be enabled, visible, and have IsTabStop and HitTestVisible property values of true. This is the default state for most controls. When a control has input focus, it can raise and respond to keyboard input events as described later in this topic. You can also respond to a control that is receiving or losing focus by handling the GotFocus and LostFocus events.

By default, the tab sequence of controls is the order in which they appear in the XAML. However, you can modify this order by using the TabIndex property. For more info, see Implementing keyboard accessibility.

Keyboard event handlers

An input event handler implements a delegate that provides the following information:

  • The sender of the event. The sender reports the object where the event handler is attached.
  • Event data. For keyboard events, that data will be an instance of KeyRoutedEventArgs. The delegate for handlers is KeyEventHandler. The most relevant properties of KeyRoutedEventArgs for most handler scenarios are Key and possibly KeyStatus.
  • OriginalSource. Because the keyboard events are routed events, the event data provides OriginalSource. If you deliberately allow events to bubble up through an object tree, OriginalSource is sometimes the object of concern rather than sender. However, that depends on your design. For more information on how you might use OriginalSource rather than sender, see the"Keyboard Routed Events" section of this topic, or Events and routed events overview.

Attaching a keyboard event handler

You can attach keyboard event-handler functions for any object that includes the event as a member. This includes any UIElement derived class. The following XAML example shows how to attach handlers for the KeyUp event for a Grid.



<Grid KeyUp="Grid_KeyUp">
  ...
</Grid>


You can also attach an event handler in code. For more info, see Events and routed events overview.

Defining a keyboard event handler

The following example shows the incomplete event handler definition for the KeyUp event handler that was attached in the preceding example.



void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
{
    //handling code here
}


Using KeyRoutedEventArgs

All keyboard events use KeyRoutedEventArgs for event data, and KeyRoutedEventArgs contains the following properties:

Key

The KeyDown event is raised if a key is pressed. Likewise, KeyUp is raised if a key is released. Usually you listen to the events to process a specific key value. To determine which key is pressed or released, check the Key value in the event data. Key returns a VirtualKey value. The VirtualKey enumeration includes all the keys supported by Windows Store apps using C++, C#, or Visual Basic.

Modifier keys

Modifier keys are keys such as Ctrl or Shift that users typically press in combination with other keys. Your app can use these combinations as keyboard shortcuts to invoke app commands.

In Windows Store apps using C++, C#, or Visual Basic, you detect shortcut key combinations by using code in your KeyDown and KeyUp event handlers. You can then track the pressed state of the modifier keys you are interested in. When a keyboard event occurs for a non-modifier key, you can check whether a modifier key is in the pressed state at the same time.

Note  The Alt key is represented by the VirtualKey.Menu value.

Shortcut keys example

The following example demonstrates how to implement shortcut keys. In this example, users can control media playback using Play, Pause, and Stop buttons or Ctrl+P, Ctrl+A, and Ctrl+S keyboard shortcuts. The button XAML shows the shortcuts by using tooltips and AutomationProperties properties in the button labels. This self-documentation is important to increase the usability and accessibility of your app. For more info, see Implementing keyboard accessibility.

Note also that the page sets input focus to itself when it is loaded. Without this step, no control has initial input focus, and the app does not raise input events until the user sets the input focus manually (for example, by tabbing to or clicking a control).


<Grid KeyDown="Grid_KeyDown">

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

  <MediaElement x:Name="DemoMovie" Source="xbox.wmv" 
    Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />

  <StackPanel Grid.Row="1" Margin="10"
    Orientation="Horizontal" HorizontalAlignment="Center">

    <Button x:Name="PlayButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+P"
      AutomationProperties.AcceleratorKey="Control P">
      <TextBlock>Play</TextBlock>
    </Button>

    <Button x:Name="PauseButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+A" 
      AutomationProperties.AcceleratorKey="Control A">
      <TextBlock>Pause</TextBlock>
    </Button>

    <Button x:Name="StopButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+S" 
      AutomationProperties.AcceleratorKey="Control S">
      <TextBlock>Stop</TextBlock>
    </Button>

  </StackPanel>

</Grid>



protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Set the input focus to ensure that keyboard events are raised.
    this.Loaded += delegate { this.Focus(FocusState.Programmatic); };
}

private void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Control) isCtrlKeyPressed = false;
}

private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Control) isCtrlKeyPressed = true;
    else if (isCtrlKeyPressed)
    {
        switch (e.Key)
        {
            case VirtualKey.P: DemoMovie.Play(); break;
            case VirtualKey.A: DemoMovie.Pause(); break;
            case VirtualKey.S: DemoMovie.Stop(); break;
        }
    }
}

private void MediaButton_Click(object sender, RoutedEventArgs e)
{
    switch ((sender as Button).Name)
    {
        case "PlayButton": DemoMovie.Play(); break;
        case "PauseButton": DemoMovie.Pause(); break;
        case "StopButton": DemoMovie.Stop(); break;
    }
}


Note  Setting AutomationProperties.AcceleratorKey or AutomationProperties.AccessKey in XAML provides string information, which documents the shortcut key for invoking that particular action. The information is captured by Microsoft UI Automation clients such as Narrator, and is typically provided directly to the user. Setting AutomationProperties.AcceleratorKey or AutomationProperties.AccessKey does not have any action on its own. You will still need to attach handlers for KeyDown or KeyUp events in order to actually implement the keyboard shortcut behavior in your app. Also, the underline text decoration for an access key is not provided automatically. You must explicitly underline the text for the specific key in your mnemonic as inline Underline formatting if you wish to show underlined text in the UI.

Keyboard routed events

Certain events are routed events, including KeyDown and KeyUp. Routed events use the bubbling routing strategy. The bubbling routing strategy means that an event originates from a child object and is then routed up to successive parent objects in the object tree. This presents another opportunity to handle the same event and interact with the same event data.

Consider the following XAML example, which handles KeyUp events for a Canvas and two Button objects. In this case, if you release a key while focus is held by either Button object, it raises the KeyUp event. The event is then bubbled up to the parent Canvas.


<StackPanel KeyUp="StackPanel_KeyUp">
  <Button Name="ButtonA" Content="Button A"/>
  <Button Name="ButtonB" Content="Button B"/>
  <TextBlock Name="statusTextBlock"/>
</StackPanel>


The following example shows how to implement the KeyUp event handler for the corresponding XAML content in the preceding example.


void StackPanel_KeyUp(object sender, KeyRoutedEventArgs e)
{
    statusTextBlock.Text = String.Format(
        "The key {0} was pressed while focus was on {1}",
        e.Key.ToString(), (e.OriginalSource as FrameworkElement).Name);
}


Notice the use of the OriginalSource property in the preceding handler. Here, OriginalSource reports the object that raised the event. The object could not be the StackPanel because the StackPanel is not a control and cannot have focus. Only one of the two buttons within the StackPanel could possibly have raised the event, but which one? You use OriginalSource to distinguish the actual event source object, if you are handling the event on a parent object.

The Handled property in event data

Depending on your event handling strategy, you might want only one event handler to react to a bubbling event. For instance, if you have a specific KeyUp handler attached to one of the Button controls, it would have the first opportunity to handle that event. In this case, you might not want the parent panel to also handle the event. For this scenario, you can use the Handled property in the event data.

The purpose of the Handled property in a routed event data class is to report that another handler you registered earlier on the event route has already acted. This influences the behavior of the routed event system. When you set Handled to true in an event handler, that event stops routing and is not sent to successive parent elements.

AddHandler and already-handled keyboard events

You can use a special technique for attaching handlers that can act on events that you already marked as handled. This technique uses the AddHandler method to register a handler, rather than using XAML attributes or language-specific syntax for adding handlers, such as += in C#. A limitation of this technique in general is that the AddHandler API takes a parameter of type RoutedEvent that identifies the routed event in question. Not all routed events provide a RoutedEvent identifier, and this consideration thus affects which routed events can still be handled in the Handled case. The KeyDown and KeyUp events have routed event identifiers (KeyDownEvent and KeyUpEvent) on UIElement. However, other events such as TextBox.TextChanged do not have routed event identifiers and thus cannot be used with the AddHandler technique.

Commanding

A small number of UI elements provide built-in support for commanding. Commanding uses input-related routed events in its underlying implementation. It enables processing of related UI input, such as a certain pointer action or a specific accelerator key, by invoking a single command handler.

If commanding is available for a UI element, consider using its commanding APIs instead of any discrete input events. For more info, see ButtonBase.Command.

You can also implement ICommand to encapsulate command functionality that you invoke from ordinary event handlers. This enables you to use commanding even when there is no Command property available.

Text input and controls

Certain controls react to keyboard events with their own handling. For instance, TextBox is a control that is designed to capture and then visually represent text that was entered by using the keyboard. It uses KeyUp and KeyDown in its own logic to capture keystrokes, then also raises its own TextChanged event if the text actually changed.

You can still generally add handlers for KeyUp and KeyDown to a TextBox, or any related control that is intended to process text input. However, as part of its intended design, a control might not respond to all key values that are directed to it through key events. Behavior is specific to each control.

As an example, ButtonBase (the base class for Button) processes KeyUp so that it can check for the Spacebar or Enter key. ButtonBase considers KeyUp equivalent to a mouse left button down for purposes of raising a Click event. This processing of the event is accomplished when ButtonBase overrides the virtual method OnKeyUp. In its implementation, it sets Handled to true. The result is that any parent of a button that is listening for a key event, in the case of a Spacebar, would not receive the already-handled event for its own handlers.

Another example is TextBox. Some keys, such as the ARROW keys, are not considered text by TextBox and are instead considered specific to the control UI behavior. The TextBox marks these event cases as handled.

Custom controls can implement their own similar override behavior for key events by overriding OnKeyDown / OnKeyUp. If your custom control processes specific accelerator keys, or has control or focus behavior that is similar to the scenario described for TextBox, you should place this logic in your own OnKeyDown / OnKeyUp overrides.

The touch keyboard

Text input controls provide automatic support for the touch keyboard. When the user sets the input focus to a text control by using touch input, the touch keyboard appears automatically. When the input focus is not on a text control, the touch keyboard is hidden.

When the touch keyboard appears, it automatically repositions your UI to ensure that the focused element remains visible. This can cause other important areas of your UI to move off screen. However, you can disable the default behavior and make your own UI adjustments when the touch keyboard appears. For more info, see Responding to the appearance of the on-screen keyboard sample.

If you create a custom control that requires text input, but does not derive from a standard text input control, you can add touch keyboard support by implementing the correct UI Automation control patterns. For more info, see the Touch keyboard sample.

Key presses on the touch keyboard raise KeyDown and KeyUp events just like key presses on hardware keyboards. However, the touch keyboard will not raise input events for Ctrl+A, Ctrl+Z, Ctrl+X, Ctrl+C, and Ctrl+V, which are reserved for text manipulation in the input control.

Related topics

Roadmaps
Roadmap for creating apps using C#, C++, or VB
Roadmap for Windows Store apps using C++
Samples
Input sample
Reference
KeyDown
KeyUp
KeyRoutedEventArgs
Concepts
Accessibility in Windows Store apps using C++, C#, or Visual Basic
Implementing keyboard accessibility
Input hosting manager and the touch keyboard

 

 

Build date: 11/29/2012

Did you find this helpful?
(1500 characters remaining)
© 2013 Microsoft. All rights reserved.