问题
I have a UserControl that adds a CommandBinding to it's CommandBindings collection to handle a specific Command. Later I use this control in a window and want to add another binding to that same control to add additional behavior. The problem though, is that when I do this it seems that when I add another CommandBinding to the CommandBindings collection of a control that it replaces any binding that was already made for the same Command. So what it seems like is that a control can only have a single CommandBinding per control, is this correct?
Please see the code example below which attempts to set two CommandBindings for the same Save Command.
<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>
Originally I was expecting either a compile-time or runtime exception when wrote this code but was surprised that it didn't complain. Next though I was disappointed since my CommandBinding_Executed handler only gets called once instead of twice as I was hoping.
Update: After a bit of testing it appears that my second CommandBinding is not overwriting my first one but instead it appears that even though I'm not setting Handled to true in my event handler that the first command binding swallows up the Command. I'm pretty sure at this point that the solution to my problem is to understand why the routed command is not propagating past the first handler even when Handled is not set to true.
Update: I've found this great little tidbit of information which just confirms some of the strange behavior behind Command routing in WPF.
Update: One thought about how to work around the fact that it appears that there can only be a single effective CommandBinding per command is that it appears that the default CommandBinding class exposes Executed and CanExecute as events which of course like all events can have multiple handlers. The idea then is to have some other way than the standard CommandBindings.Add method to add additional handlers to a command. Maybe this could be done via an extension method on the Control class and conjunction with a custom CompositeCommandBinding class which allows us to aggregate multiple bindings within one main binding.
回答1:
So far I've only been able to come up with a workaround for this problem which is to handle the command at two different levels in the logical tree. In the example below I handle the Save command within my grid and then also again within the Window element.
<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>
In order to get this to work my code behind needs to also manually propagate the Command execution to the next level up.
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!");
}
If anybody has any better ideas on how I can monitor a command still let it propagate naturally up the tree I would love to see it otherwise I might just resort to this workaround.
回答2:
I don't know the answer to your question, but using Reflector sounds reasonable to me.
I'm wondering why are you doing this? Maybe it makes more sense to use Composite pattern to aggregate behaviors, rather then trying to combine command bindings?
来源:https://stackoverflow.com/questions/2290142/can-i-have-multiple-commandbindings-for-the-same-command-on-the-same-control