我可以在同一个控件上为同一个命令设置多个CommandBinding吗?

时间:2010-02-18 16:18:44

标签: wpf command commandbinding

我有一个UserControl,它将CommandBinding添加到它的CommandBindings集合中以处理特定的Command。后来我在一个窗口中使用此控件,并希望向该控件添加另一个绑定以添加其他行为。但问题是,当我这样做时,似乎当我将另一个CommandBinding添加到控件的CommandBindings集合时,它取代了已经为同一个Command创建的任何绑定。那么看起来控件每个控件只能有一个CommandBinding,这是正确的吗?

请参阅下面的代码示例,该示例尝试为同一个Save Command设置两个CommandBinding。

<Window x:Class="MultipleCommandBindings.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
    <CommandBinding Command="Save"
                    Executed="CommandBinding_Executed" />
    <CommandBinding Command="Save"
                    Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<Grid>
    <Button Height="23"
            HorizontalAlignment="Right"
            Margin="0,0,25,88"
            Name="button1"
            VerticalAlignment="Bottom"
            Width="75"
            Command="Save">Button</Button>
</Grid>

最初我在编写此代码时期望编译时或运行时异常,但对它并没有抱怨感到惊讶。接下来虽然我很失望,因为我的CommandBinding_Executed处理程序只被调用一次而不是我希望的两次。

更新 经过一些测试后,看来我的第二个CommandBinding没有覆盖我的第一个但是看起来即使我没有在我的事件处理程序中将Handled设置为true,第一个命令绑定吞下了Command。我非常确定在这一点上我的问题的解决方案是理解为什么路由命令没有传播通过第一个处理程序,即使Handled未设置为true。

更新 我发现this great little tidbit信息只是确认了WPF中命令路由背后的一些奇怪行为。

更新 有人想过如何解决每个命令只能有一个有效的CommandBinding这一事实,看来默认的CommandBinding类公开Executed和CanExecute作为事件,当然所有事件都可以有多个处理程序。然后,我们的想法是使用标准CommandBindings.Add方法之外的其他方法向命令添加其他处理程序。也许这可以通过Control类上的扩展方法完成,并与自定义CompositeCommandBinding类结合使用,该类允许我们在一个主绑定中聚合多个绑定。

2 个答案:

答案 0 :(得分:3)

到目前为止,我只能为此问题找到解决方法,即在逻辑树中的两个不同级别处理命令。在下面的示例中,我在网格中处理Save命令,然后在Window元素中再次处理。

<Window x:Class="MultipleCommandBindings.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
    <CommandBinding Command="Save"
                    Executed="CommandBinding_Executed2"/>
</Window.CommandBindings>
<Grid>
    <Grid.CommandBindings>
        <CommandBinding Command="Save"
                        Executed="CommandBinding_Executed1" />
    </Grid.CommandBindings>

    <Button Height="23"
            HorizontalAlignment="Right"
            Margin="0,0,25,88"
            Name="button1"
            VerticalAlignment="Bottom"
            Width="75"
            Command="Save">Button</Button>
</Grid>

为了使其工作,我的代码背后还需要手动将Command执行传播到下一级别。

    private void CommandBinding_Executed1(object sender, ExecutedRoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Executed 1!");
        var command = e.Command as RoutedUICommand;
        command.Execute(e.Parameter, this);
    }

    private void CommandBinding_Executed2(object sender, ExecutedRoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Executed 2!");
    }

如果有人对如何监控命令有任何更好的想法仍然让它自然地在树上传播,我很乐意看到它,否则我可能只是采用这种解决方法。

答案 1 :(得分:1)

我不知道你问题的答案,但使用Reflector对我来说听起来很合理。

我想知道你为什么要这样做?使用Composite模式聚合行为,而不是尝试组合命令绑定更有意义吗?