2012-04-13 105 views
1

讓我們從元素樹開始。最上面的元素是一個WPF窗口,它已經註冊了ApplicationCommands.Find命令。 某些子元素具有KeyBinding,並且手勢鍵ENTER指向此命令。這沒關係,如果有人按下ENTER鍵,命令將被執行。 其中我有一個自定義控件,用於搜索和選擇一些元素的彈出窗口。在這個地方,雖然, 我不想讓自定義控件之外的關鍵事件冒泡。但我設置e.handled = trueKeyDown += new KeyEventHandler (..),這應該是冒泡路由事件,該自定義控件內的所有控件(文本框等)都將忽略任何類型的輸入。 但我只是想停止在CustomControl的級別冒泡,說:從葉子到最頂層的控制父級,而不是進一步! 這是爲什麼?我不過濾PreviewKeyDown,所以事件必須傳播到葉,然後它應該回到父,但它不。WPF防止事件在控件之外冒泡

謝謝

編輯:示例代碼:

<UserControl x:Class="WpfApplication5.TestUserControl" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    > 
    <StackPanel Orientation="Vertical">   
     <TextBox /> 
     <TextBox /> 
     <TextBox /> 
    </StackPanel> 
</UserControl> 


/* 
* I want to stop bubbling at this level. Let us say if we click 'enter' on the level of the TextBox leaf, 
* it should propagate until the TestUserControl is reached and then stop. 
*/ 
public partial class TestUserControl : UserControl 
{ 
    public TestUserControl() 
    { 
     InitializeComponent(); 
    } 
} 


<Window x:Class="WpfApplication5.Window6" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication5" 
    Title="Window6" Height="300" Width="300"> 
    <Window.CommandBindings> 
     <CommandBinding Command="ApplicationCommands.Find" Executed="CommandBinding_Executed" /> 
    </Window.CommandBindings> 
    <Window.InputBindings> 
     <KeyBinding Gesture="Enter" Command="ApplicationCommands.Find" /> 
    </Window.InputBindings> 
    <Grid> 
     <local:TestUserControl /> 
    </Grid> 
</Window> 

public partial class Window6 : Window 
{ 
    public Window6() 
    { 
     InitializeComponent(); 
    } 

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     MessageBox.Show("Executed"); 
    } 
} 

回答

1

你想從您的自定義控制彌合事件到你的窗口,對不對? 然後,您必須重新啓動系統窗口中的事件來照顧它。如果您只將其標記爲已處理,則意味着不會再採取進一步的行動。

代碼應該是這樣的:

private void CustomControl_KeyDown(object sender, KeyEventArgs e) 
{ 
    e.Handled = true; 
    var relaunchedEvent = new KeyEventArgs(e.KeyboardDevice, e.InputSource, e.Timestamp, e.Key); 
    relaunchedEvent.RoutedEvent = Keyboard.KeyDownEvent; 
    relaunchedEvent.Source = e.OriginalSource; 
    TopMostWindow.RaiseEvent(relaunchedEvent); 
} 

- 編輯 -

測試上面下面的XAML代碼,看keydown事件是如何在窗戶開不執行命令。

<Window x:Class="WpfApplication5.Window6" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication5" 
    Title="Window6" Height="300" Width="300" 
    x:Name="TopMostWindow"> 
    <Grid> 
     <Grid KeyDown="CustomControl_KeyDown"> 
      <local:UserControl1/> 
     </Grid> 
     <Grid.CommandBindings> 
      <CommandBinding Command="ApplicationCommands.Find" Executed="CommandBinding_Executed" /> 
     </Grid.CommandBindings> 
     <Grid.InputBindings> 
      <KeyBinding Key="Enter" Command="ApplicationCommands.Find" /> 
     </Grid.InputBindings> 
    </Grid> 
</Window> 

重要提示:

  • 命令都處於較高的水平,所以也無所謂無論您使用起泡或隧道事件,最終命令將被除非該事件被標記執行作爲處理。
  • 提高Keydown事件實際上並不意味着按下鍵,因爲文本構成不會發生。

對於您的情況,我的建議是過濾您的用戶控件中的keydown事件,並將其標記爲e.Key=Key.Enter,因爲Enter對文本框沒有太大的作用。否則,你將不得不模擬按鍵。

+0

不完全。我想停止傳播事件到自定義控件的主窗口..但是,謝謝 – 2012-04-17 07:07:40

+0

這就是我所理解的。我認爲一些代碼可能會有幫助。 – Natxo 2012-04-17 08:26:41

+1

嗨PaN1C,我編輯我的答案後,您的示例代碼 – Natxo 2012-04-18 08:51:07