2

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

ありがとうございました

編集: サンプルコード:

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

1 に答える 1

3

カスタム コントロールからウィンドウにイベントをブリッジしたいと思いませんか? 次に、システムが処理できるように、ウィンドウからイベントを再起動する必要があります。処理済みとしてマークするだけであれば、それ以上のアクションは行われないことを意味します。

コードは次のようになります。

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です。それ以外の場合は、キーの押下をシミュレートする必要があります。

于 2012-04-13T11:10:53.183 に答える