7

私の問題は、複数の場所でコマンドを処理したいということです。たとえば、ボタンがいくつかのコマンドにバインドされているカスタム UserControl があります。そのコントロールにはコマンド バインディングがありますが、このコントロールを使用するウィンドウにもコマンド バインディングがあります。

私の目的は、ウィンドウでのコマンドの処理を中断せずに、コントロール内で何らかのアクションを実行することです。

Executed および PreviewExecuted イベントを試してみましたが、うまくいきませんでした。次に、単一のウィンドウで問題をシミュレートしました (以下に投稿されたコード)。

<Window x:Class="CommandingEvents.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:CommandingEvents="clr-namespace:CommandingEvents" 
    Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
    <CommandBinding 
        Command="{x:Static CommandingEvents:Window1.Connect}"
        Executed="CommandBindingWindow_Executed"
        PreviewExecuted="CommandBindingWindow_PreviewExecuted"/>
</Window.CommandBindings>
<Grid>
    <Grid.CommandBindings>
        <CommandBinding 
        Command="{x:Static CommandingEvents:Window1.Connect}"
        Executed="CommandBindingGrid_Executed"
        PreviewExecuted="CommandBindingGrid_PreviewExecuted" />
    </Grid.CommandBindings>
    <Button Command="{x:Static CommandingEvents:Window1.Connect}" 
            CommandTarget="{Binding RelativeSource={RelativeSource Self}}"
            Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>

namespace CommandingEvents
{
    public partial class Window1
    {
        public static readonly RoutedUICommand Connect = new
            RoutedUICommand("Connect", "Connect", typeof(Window1));

        public Window1()
        {
            InitializeComponent();
        }

        private void CommandBindingWindow_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingWindow_Executed");
            e.Handled = false;
        }

        private void CommandBindingGrid_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingGrid_Executed");
            e.Handled = false;
        }

        private void CommandBindingWindow_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingWindow_PreviewExecuted");
            e.Handled = false;
        }

        private void CommandBindingGrid_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingGrid_PreviewExecuted");
            e.Handled = false;
        }
    }
}

ボタンを押すと、「CommandBindingWindow_PreviewExecuted」のみが出力されます。何故ですか?e.Handled を false に設定しようとしましたが、違いはありません。誰でもこの動作を説明できますか?

4

1 に答える 1

10

なぜそれが発生するのか(そしてそれがどのようにバグではないのか)はわかりませんが、WPFwikiに書かれているものは次のとおりです。

CommandBindingには、非常に興味深く、知っておくことが重要な特殊性があります。

CommandManagerは、ルーティングされたイベントを使用して、コマンドの実行が呼び出されたことをさまざまなCommandBindingオブジェクトに通知します(デフォルトのジェスチャ、入力バインディング、明示的な方法など)。

これまでのところ、これはかなり簡単です。ただし、より重要なのは、CommandBindingが、ハンドラーが実行されるとすぐに(PreviewExecutedまたはExecuted)、CommandManagerからルーティングされたイベントを処理済みとしてマークすることです。

最後に、ハンドラーにExecutedRoutedEventHandlerというデリゲートと一致するプロトタイプがある場合でも、CommandBindingからのExecutedイベントはRoutedEventではなく、通常のCLRイベントです。e.Handledフラグをfalseに設定またはそのままにしておくと、何も変更されません。

したがって、ExecutedまたはPreviewExecutedハンドラーが呼び出されるとすぐに、RoutedCommandはそのルーティングを停止します。

于 2011-02-02T16:49:50.650 に答える