Wpf 是否可以全局检测键盘焦点事件?

Wpf 是否可以全局检测键盘焦点事件?,wpf,Wpf,可以使用以下事件,但必须为每个元素附加这些事件: GotKeyboardFocus,LostKeyboardFocus 在.NET WPF中是否有一种方法可以全局检测聚焦元素是否发生了更改?不必为所有可能的元素添加事件侦听器 您可以将路由事件处理程序添加到主窗口,并指定您对已处理事件感兴趣 mainWindow.AddHandler( UIElement.GotKeyboardFocusEvent, OnElementGotKeyboardFocus, true );

可以使用以下事件,但必须为每个元素附加这些事件:

GotKeyboardFocus,LostKeyboardFocus


在.NET WPF中是否有一种方法可以全局检测聚焦元素是否发生了更改?不必为所有可能的元素添加事件侦听器

您可以将路由事件处理程序添加到主窗口,并指定您对已处理事件感兴趣

mainWindow.AddHandler(
    UIElement.GotKeyboardFocusEvent,
    OnElementGotKeyboardFocus,
    true
);
您可以挂钩到预览事件:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="350" Width="525" 
    PreviewGotKeyboardFocus="Window_PreviewGotKeyboardFocus" 
    PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus">
....

....
这样,如上所示,当任何子体获取或丢失键盘焦点时,窗口将在所有子体之前得到通知


阅读以了解更多信息。

您可以在任何课堂上使用以下工具执行此操作:

//In the constructor
EventManager.RegisterClassHandler(
        typeof(UIElement),
        Keyboard.PreviewGotKeyboardFocusEvent,
        (KeyboardFocusChangedEventHandler)OnPreviewGotKeyboardFocus);


查看Microsoft在焦点更改时如何触发CommandManager.RequerySuggest事件:他们订阅事件

简单的例子:

static KeyboardControl()
{
    InputManager.Current.PostProcessInput += InputManager_PostProcessInput;
}

static void InputManager_PostProcessInput(object sender, ProcessInputEventArgs e)
{
    if (e.StagingItem.Input.RoutedEvent == Keyboard.GotKeyboardFocusEvent ||
        e.StagingItem.Input.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
    {
        KeyboardFocusChangedEventArgs focusArgs = (KeyboardFocusChangedEventArgs)e.StagingItem.Input;
        KeyboardControl.IsOpen = focusArgs.NewFocus is TextBoxBase;
    }
}

这也适用于多窗口应用程序。

由于这是一个预览事件,因此此方法可能会导致不正确的结果,因此焦点更改可能不会实际发生。如果窗口和源元素之间的UIElement将事件标记为已处理,则会发生这种情况。我同意@Hank。PreviewXxx并不保证它会真正改变。瓦卡诺的答案实际上是正确的。Nicolas还有一个备选方案,虽然不完全相同,因为链中的每个人都会因为处理事件的失败而得到通知。@MarkA.Donohoe你说PreviewXXX不能保证,但你也说Vaccano的答案(也使用PreviewXXX)是吗?我想你是对的…它应该讨论的是用常规的gotfocus事件注册类处理程序,而不是previewgotfocus事件。键是类处理程序而不是常规事件处理程序。谢谢。我在处理程序中使用以下代码选择文本框的所有文本:if(e.NewFocus是TextBoxBase textBox)textBox.SelectAll();
static KeyboardControl()
{
    InputManager.Current.PostProcessInput += InputManager_PostProcessInput;
}

static void InputManager_PostProcessInput(object sender, ProcessInputEventArgs e)
{
    if (e.StagingItem.Input.RoutedEvent == Keyboard.GotKeyboardFocusEvent ||
        e.StagingItem.Input.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
    {
        KeyboardFocusChangedEventArgs focusArgs = (KeyboardFocusChangedEventArgs)e.StagingItem.Input;
        KeyboardControl.IsOpen = focusArgs.NewFocus is TextBoxBase;
    }
}