Search code examples
c#wpfuser-controlsfocus

WPF UserControl detect LostFocus ignoring children


I have a UserControl hat contains several elements (ListBoxes, Buttons) and a Popup with ComboBoxes and Buttons.

I tried lost focus on the user contorl, but whenever the focus inside the UserControl changes, the Lost(Keyboard)Focus event fires.

But I don't want to know when a child loses focus to another child of the UserControl, but I want to know, when the keyboard focus moves to an element outside the UserControl and it's Popup.

Is there a way to detect that, without checking the LostFocus of every single element?


Solution

  • Does this solution suit you? I've created new event, called LostFocusIgnoreChildren in the UserControl, which fires only if new focused element is not a child of this UserControl.

    UserControl1.cs

      public partial class UserControl1 : UserControl
        {
            public UserControl1()
            {
                InitializeComponent();
            }
    
            public event RoutedEventHandler LostFocusIgnoreChildren;
            private void UserControl_LostFocus(object sender, RoutedEventArgs e)
            {
                var focused_element = FocusManager.GetFocusedElement(Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive));
                var parent = (focused_element as FrameworkElement).TryFindParent<UserControl1>();
                if (parent == null && LostFocusIgnoreChildren != null)
                    LostFocusIgnoreChildren(this, e);
            }
        }
    

    VisualTreeHelper extensions

     public static class VisualTreeHelperExt
        {
            public static T TryFindParent<T>(this DependencyObject child)
        where T : DependencyObject
            {
                DependencyObject parentObject = GetParentObject(child);
                if (parentObject == null) return null;
                T parent = parentObject as T;
                if (parent != null)
                {
                    return parent;
                }
                else
                {
                    return TryFindParent<T>(parentObject);
                }
            }
    
            public static DependencyObject GetParentObject(this DependencyObject child)
            {
                if (child == null) return null;
                ContentElement contentElement = child as ContentElement;
                if (contentElement != null)
                {
                    DependencyObject parent = ContentOperations.GetParent(contentElement);
                    if (parent != null) return parent;
                    FrameworkContentElement fce = contentElement as FrameworkContentElement;
                    return fce != null ? fce.Parent : null;
                }
                FrameworkElement frameworkElement = child as FrameworkElement;
                if (frameworkElement != null)
                {
                    DependencyObject parent = frameworkElement.Parent;
                    if (parent != null) return parent;
                }
                return VisualTreeHelper.GetParent(child);
            }
        }