#620 – Why Are There So Many KeyPress Events?

When you press a single key within a WPF application, there are potentially a number of different keypress events that can fire.  But why are there so many different events that can possibly fire?

There are several reasons why there isn’t just a single keypress event.

  • Your application will only see the events for which you define a handler.  There is a large set of possible events so that you can choose which ones make sense for your application to handle.
  • Preview events exist so that a parent control can intercept keypress events for its children or descendants.  The tunneling allows you to decide at what level you want to preview the event.
  • The actual keypress event bubbles up the logical tree so that you can decide at what level to actually respond to the event.  In this way, you can handle multiple events in a single place.

#619 – Event Sequence for the Key Up/Down Events

There are four basic events related to a key being pressed or released that a GUI element can fire in WPF.  An event fires when you press a key down (KeyDown) and a different event fires when you release the key (KeyUp).  When these events fire for an element, they fire first for the element and then work back up the logical tree, firing for each ancestor element.  These are bubbling events.

There are also the PreviewKeyDown and PreviewKeyUp events, which fire before the KeyDown and KeyUp events, but fire from the top of the logical tree down to the control where the event originated.  (Tunneling events).

For a Window containing a StackPanel that contains a TextBox, the event sequence when a user presses a key while the TextBox has focus is:

  • Window_PreviewKeyDown
  • StackPanel_PreviewKeyDown
  • TextBox_PreviewKeyDown
  • TextBox_KeyDown
  • StackPanel_KeyDown
  • Window_KeyDown
  • Window_PreviewKeyUp
  • StackPanel_PreviewKeyUp
  • TextBox_PreviewKeyUp
  • TextBox_KeyUp
  • StackPanel_KeyUp
  • Window_KeyUp

 

#588 – If You Handle PreviewKeyDown Event, KeyDown Won’t Fire

The PreviewKeyDown and KeyDown events in WPF are paired routed events.  When a user presses a key in a control, the PreviewKeyDown event fires first, as a tunneling event.  When the event has propagated down the logical tree to the control where the key press originated, the KeyDown event fires.  KeyDown propagates up the logical tree, since it is defined as a bubbling event.

If you handle the PreviewKeyDown event as it is propagating down the tree and you mark the event as handled (setting KeyEventArgs.Handled to true), the PreviewKeyDown event will not continue propagating down the tree.

But if you mark PreviewKeyDown as handled, the corresponding KeyDown event will not fire at all.  This works because the two events share the same instance of a KeyEventArgs object, so when PreviewKeyDown marks the event as handled, KeyDown also treats the event as handled.

#586 – Bubbling and Tunneling Events Are Typically Paired

Events defined for preexisting controls in WPF (e.g. a Button) are typically routed events–meaning that the event is propagated up or down the logical tree.  Routed events can either be bubbling events (they propagate up the tree) or tunneling events (they propagate down the tree).

Many events in WPF related to user input are available in pairs, with both a bubbling and a corresponding tunneling event.  For example, the KeyDown event (bubbling) has a corresponding PreviewKeyDown event (tunneling).

When events are paired, the tunneling events will typically fire first, followed by the paired bubbling event.

  1. User presses key
  2. Main Window sees PreviewKeyDown
  3. Outer StackPanel sees PreviewKeyDown
  4. Inner StackPanel sees PreviewKeyDown
  5. TextBox sees PreviewKeyDown
  6. TextBox sees KeyDown
  7. Inner StackPanel sees KeyDown
  8. Outer StackPanel sees KeyDown
  9. Main Window sees KeyDown

#581 – An Example of a Routed Event

In WPF, events that fire as a result of interacting with user interface elements are routed up or down a tree of user interface elements.

In the example below, we’ve attached a handler for the KeyDown event to the first TextBox control.  We also define handlers for the StackPanel that contains this TextBox, as well as the higher level StackPanel and the main Window.

Displaying a message from within each of these event handlers, we see the following output when we move focus to the TextBox and then press a key.

Four events are fired, starting in the TextBox and then preceding up the logical tree.  The event travels up the tree because KeyDown is a bubbling event–it “bubbles up” the logical tree.

In each handler, e.Source refers to control where the event originated and Sender refers to the control that owns the handler.

#204 – Detecting Key Presses in a WPF Window

You can detect key presses in a class that derives from Window by overriding the OnKeyDown and OnKeyUp methods (which in turn fire the KeyDown and KeyUp events).  

These key down/up methods are invoked in addition to any control that has focus and might also provide key down/up methods.

For example, a TextBox also has KeyDown and KeyUp events that are fired.  If a user presses a key while a TextBox has focus, the sequence of events is:

  • KeyDown in TextBox
  • KeyDown in Window
  • KeyUp in TextBox
  • KeyUp in Window

Here’s an example:

    public partial class MainWindow : Window
    {
        private static Key[] vowels = { Key.A, Key.E, Key.I, Key.O, Key.U };

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            if ((vowels.Contains(e.Key)) && (!e.IsRepeat))
                lblVowels.Content = lblVowels.Content + e.Key.ToString();
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);

            if (vowels.Contains(e.Key))
                lblVowels.Content = lblVowels.Content + ",";
        }