WPF UserControl 检测 LostFocus 忽略儿童
WPF UserControl detect LostFocus ignoring children
我有一个 UserControl 帽子,其中包含多个元素(ListBoxes、Buttons)和一个带有 ComboBoxes 和 Buttons 的 Popup。
我试过在用户控件上失去焦点,但只要 UserControl 中的焦点发生变化,Lost(Keyboard)Focus 事件就会触发。
但我不想知道一个子项何时将焦点转移到 UserControl 的另一个子项,但我想知道,何时键盘焦点移动到 UserControl 外部的元素并且它是 Popup。
有没有办法在不检查每个元素的 LostFocus 的情况下检测到这一点?
这个解决方案适合你吗?我在 UserControl 中创建了名为 LostFocusIgnoreChildren
的新事件,只有当新的焦点元素不是此 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 扩展
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);
}
}
这样做更容易:
private void UserControl_LostFocus(object sender, RoutedEventArgs e)
{
if (!this.IsKeyboardFocusWithin)
{
_lastFocusedElement = e.OriginalSource as IInputElement;
}
}
我有一个 UserControl 帽子,其中包含多个元素(ListBoxes、Buttons)和一个带有 ComboBoxes 和 Buttons 的 Popup。
我试过在用户控件上失去焦点,但只要 UserControl 中的焦点发生变化,Lost(Keyboard)Focus 事件就会触发。
但我不想知道一个子项何时将焦点转移到 UserControl 的另一个子项,但我想知道,何时键盘焦点移动到 UserControl 外部的元素并且它是 Popup。
有没有办法在不检查每个元素的 LostFocus 的情况下检测到这一点?
这个解决方案适合你吗?我在 UserControl 中创建了名为 LostFocusIgnoreChildren
的新事件,只有当新的焦点元素不是此 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 扩展
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);
}
}
这样做更容易:
private void UserControl_LostFocus(object sender, RoutedEventArgs e)
{
if (!this.IsKeyboardFocusWithin)
{
_lastFocusedElement = e.OriginalSource as IInputElement;
}
}