2012-04-24 71 views

回答

3

你可以連接到tunneling預覽事件:

<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"> 
.... 

這樣,如上圖所示,該窗口將所有後代之前當任何後代獲得或失去鍵盤焦點通知。

閱讀this瞭解更多信息。

+1

由於這是一個預覽事件,因此此方法可能會導致錯誤結果,因此焦點更改可能不會真正發生。如果窗口和源元素之間的UIElement將事件標記爲已處理,則會發生這種情況。 – Hank 2014-02-03 20:26:34

+0

我同意@Hank。 PreviewXxx不保證它實際上會改變。 Vaccano的答案其實是正確的。尼古拉斯也有替代品,儘管並不完全一樣,因爲處理事件的失敗導致連鎖店中的每個人都得到通知。 – MarqueIV 2015-11-04 16:24:17

5

您可以將路由事件處理程序添加到主窗口並指定您對處理的事件感興趣。

mainWindow.AddHandler(
    UIElement.GotKeyboardFocusEvent, 
    OnElementGotKeyboardFocus, 
    true 
); 
+0

工作完美!非常感謝! – Alexey 2014-05-09 08:08:59

12

您可以在任何類此這樣做:

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

...

private void OnPreviewGotKeyboardFocus(object sender, 
             KeyboardFocusChangedEventArgs e) 
{ 

    // Your code here 

} 
0

看一看微軟如何觸發CommandManager.RequerySuggested事件當焦點的變化:他們訂閱InputManager.PostProcessInput事件。

ReferenceSource

簡單的例子:

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; 
    } 
} 

這也適用於多窗口的應用程序。