2011-01-12 10 views
6

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

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

私はExecutedイベントとPreviewExecutedイベントを試してみましたが、運はありませんでした。次に、問題を1つのウィンドウでシミュレートしました(下に掲載されたコード)。

<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に設定しようとしましたが、違いはありません。誰もこの行動を説明できますか?

答えて

9

私はそれがなぜ起こるかのアイデア(とどのようにそれはバグではありません)を持っていないが、ここWPF wikiで書かれたものです。

極めて 面白いです いるCommandBindingに関する特殊性があると知ることが重要です。

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

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

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

したがって、できるだけ早く実行したり PreviewExecutedハンドラが呼び出されるよう、 RoutedCommandのは、その ルーティングを停止します。

+1

'RoutedCommand'に強制的にルーティングさせる方法はありますか? –

+0

@Matthew:まあ、Executedメソッドからイベントを再発生させることができます。 – VitalyB

+0

WPF wikiへのリンクが死んでいます。それはどこかに移動しましたか? – dtm