7

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

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

我尝试尝试 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

我不知道为什么会发生这种情况(以及它如何不是错误),但这是WPF wiki中所写的内容:

CommandBinding 有一个特殊性,它非常有趣且非常重要。

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

到目前为止,这相当简单。然而,更重要的是,一旦处理程序被执行(PreviewExecuted 或 Executed),CommandBinding 就会将来自 CommandManager 的路由事件标记为已处理。

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

因此,一旦调用了 Executed 或 PreviewExecuted 处理程序,RoutedCommand 将停止其路由。

于 2011-02-02T16:49:50.650 回答