Reputation: 82291
I have this code:
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this,
OnMouseDownOutsideCapture);
And it fully captures when a mouse click happens outside my WPF Popup (so I can close it).
private void OnMouseDownOutsideCapture(object sender, MouseButtonEventArgs e)
{
if (Mouse.Captured is ComboBox) return;
if (IsOpen)
IsOpen = false;
ReleaseMouseCapture();
}
But I need some way to know if the focus is moved outside my popup via the keyboard. More specifically by an shortcut (ie Alt + T).
Right now, my popup does not close when the user moves focus off it that way. Any ideas?
Upvotes: 2
Views: 367
Reputation: 82291
This is how I did it:
Add this to the constructor:
EventManager.RegisterClassHandler(typeof(UIElement),
Keyboard.PreviewGotKeyboardFocusEvent,
(KeyboardFocusChangedEventHandler)OnPreviewAnyControlGotKeyboardFocus);
Then add this event handler:
/// <summary>
/// When focus is lost, make sure that we close the popup if needed.
/// </summary>
private void OnPreviewAnyControlGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
// If we are not open then we are done. No need to go further
if (!IsOpen) return;
// See if our new control is on a popup
var popupParent = VLTreeWalker.FindParentControl<Popup>((DependencyObject)e.NewFocus);
// If the new control is not the same popup in our current instance then we want to close.
if ((popupParent == null) || (this.popup != popupParent))
{
popupParent.IsOpen = false;
}
}
VLTreeWalker is a custom class that walks up the visual tree looking for a match to the passed in generic type and then (if it does not find a matching item, will walk up the logical tree.) Sadly, I can't easily post the source for that here.
this.popup
is the instance that you are comparing against (that you want to know if it should close).
Upvotes: 1