RoutedCommands Executed和PreviewExecuted事件

ser*_*ine 6 wpf routed-commands

我的问题是我想在多个地方处理命令.例如,我有自定义的UserControl,其中Button被绑定到某个命令.我在该控件中有一个命令绑定,但我在一个使用该控件的Window中也有一个命令绑定.

我的目标是在控件内执行一些操作,同时不中断窗口中命令的处理.

我尝试过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>
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我按下按钮时,只打印出"CommandBindingWindow_PreviewExecuted".这是为什么?我试图将e.Handled设置为false,但它没有任何区别.谁能解释这种行为?

Vit*_*lyB 9

我不知道为什么会发生这种情况(以及它不是一个错误)但是这里是WPF wiki中写的:

CommandBinding有一个特殊之处,它非常有趣且非常重要.

CommandManager使用路由事件来通知不同的CommandBinding对象调用命令执行(通过默认手势,输入绑定,显式等).

到目前为止,这是相当简单的.但是,更重要的是CommandBinding将在处理程序执行后立即将CommandManager中的路由事件标记为处理(PreviewExecuted或Executed).

最后,即使您的处理程序具有与名为ExecutedRoutedEventHandler的委托相匹配的原型,CommandBinding中的Executed事件也不是RoutedEvent而是普通的CLR事件.将e.Handled标志设置或保留为false将不会改变任何内容.

因此,只要调用Executed或PreviewExecuted处理程序,RoutedCommand就会暂停其路由.