2012-04-13 34 views
1

要素ツリーから始めましょう。一番上の要素は、ApplicationCommands.Findコマンドを登録したWPFウィンドウです。 一部の子要素には、このコマンドを指し示すジェスチャーキーENTERを持つKeyBindingがあります。それはOKです。誰かがENTERを押すとコマンドが実行されます。 中には、いくつかの要素を検索して選択するためのポップアップを備えたカスタムコントロールがあります。しかし、この場所では、 私はカスタムコントロールの外でキーイベントのバブリングを許可したくありません。しかし、私は KeyDown += new KeyEventHandler (..)のためにe.handled = trueを設定します。これは、バブリングされたルーティングイベントであると想定されています。そのカスタムコントロール内のすべてのコントロール(テキストボックスなど)は、あらゆる種類の入力を無視します。 しかし、私はCustomControlのレベルで、葉から最上位のコントロールの親まで、それ以上のバブリングを止めたいだけです! なぜですか?私はPreviewKeyDownをフィルタリングしていないので、イベントはリーフまで伝播していなければなりません。そして、親に戻るべきですが、そうではありません。サンプルコード: WPFは、コントロールの外部でイベントのバブリングを防止します。

はあなたに

EDITEDありがとう

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

- EDIT -

テスト次の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

正確ではありません。私はカスタムコントロールからのメインウィンドウにイベントを伝播を停止したいです。しかし、ありがとう –

+0

それは私が理解したものです。私はいくつかのコードが役立つかもしれないと思う。 – Natxo

+1

こんにちはPaN1C、私はあなたのサンプルコード – Natxo

関連する問題