Keyboard Friendly WPF Popup Control

A couple of weeks ago I talked about various tips for building more keyboard friendly WPF application, now I will I am going to focus about the WPF Popup control.

To make the popup control more keyboard friendly we need to make the following changes:
  1. When the popup opens, the keyboard focus should move to the contents of the popup.
  2. Lock the keyboard focus inside the popup until it closes.
To do this, I created the "FriendlyPopup" control (or "EnhancedPopup" or whatever):

  public class FriendlyPopup : Popup
  {
    protected override void OnOpened(EventArgs e)
    {
      base.OnOpened(e);

      // move the focus into the popup when it opens.
      this.Child.MoveFocus(new TraversalRequest(
        FocusNavigationDirection.Next));
    }

    protected override void OnLostKeyboardFocus(
      KeyboardFocusChangedEventArgs e)
    {
      base.OnLostKeyboardFocus(e);

      // if the focus is still inside the popup, 
      // don't do anything.
      if (this.IsKeyboardFocusWithin)
        return;

      // if the popup is still open, keep the focus inside.
      if (this.IsOpen)
        this.Child.MoveFocus(new TraversalRequest(
          FocusNavigationDirection.Next));
    }
  }

Comments

Anonymous said…
hi David i need to contact you personally. my email is vasago007@hotmail.com
Mitan Shah said…
Hi David,

How can i make popup which can auto close with Tab Navigation continue back to main window.
David Elentok said…
Hi Mitan, I'm not sure I understand what you mean, what do you mean by "auto close"?
Anonymous said…
@Mitan Shaw -
Try putting a as the last control on your popup.

Then when it gets focus, close the popup.

In the Closed event for the popup, set the focus to the control you want.

I tried other combinations of this and it has problems. But these steps worked for me.
Anonymous said…
The last control was supposed to be:

TextBox Width="1" Opacity="0"

The angle brackets got it chopped.
EU said…
That was exacly what i needed! Thanks 4 the post!
Vojtech Dohnal said…
Great tip, thanks.
However, when there are more than one friendly popup open (e.g. using keyborad shortcut), there is a neverending cycle between popus trying to set its own focus in OnLostKeyboardFocus.
Some anti cycling code should be added before:
// if the popup is still open, keep the focus inside.
if (this.IsOpen)
this.Child.MoveFocus(new TraversalRequest(
FocusNavigationDirection.Next));

Popular posts from this blog

Restart the Windows File Sharing Service to fix weird problems

WPF, ImageSource and Embedded Resources

SharpDevelop dark color scheme