I have some CommandBindings
(in a Window
) that work with MenuItem
s (by "work" I mean the executed
/canexecute
handlers are called),
I have others (in a UserControl
) that work when assigned to the Command
properties of Button
s (the handlers are called) -- but not when used with MenuItem
s (the handlers are never called).
I can make a MenuItem
interact correctly with a CommandBinding
in the UserControl
by copying and pasting each binding into the appropriate MenuItem.CommandBindings
, like so:
<MenuItem
Header="Select All"
Command="{StaticResource SelectAllCommand}"
>
<MenuItem.CommandBindings>
<CommandBinding
Command="{StaticResource SelectAllCommand}"
Executed="SelectAll_Executed"
CanExecute="SelectAll_CanExecute"
/>
</MenuItem.CommandBindings>
</MenuItem>
But that's silly (and see below).
I can also make them work by copying the UserControl
's command bindings up to the window in the UserControl
's constructor:
C#
Application.Current.MainWindow.CommandBindings.AddRange(this.CommandBindings);
Again, that's pretty crazy, but it does seem to imply that there's a contextual factor at work here.
I copied the relevant bits of the control XAML into the following test XAML to reproduce the issue, but the issue didn't reproduce. Unlike the production code I extracted it from, it works as you'd expect: It's a binding, it's bound, it calls the methods. But the exact same method of binding event handler methods to commands to menuitems fails in a different UserControl
in a different (and incompably vaster and more complicated) project.
XAML:
<UserControl
x:Class="CommandTest.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
>
<UserControl.Resources>
<ResourceDictionary>
<RoutedUICommand x:Key="TestCommand" />
<ContextMenu x:Key="TestMenu">
<MenuItem
Header="_Test"
Command="{StaticResource TestCommand}"
/>
</ContextMenu>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.CommandBindings>
<CommandBinding
Command="{StaticResource TestCommand}"
Executed="TestCommand_Executed"
CanExecute="TestCommand_CanExecute"
/>
</UserControl.CommandBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox
Width="200"
ContextMenu="{StaticResource TestMenu}"
/>
</Grid>
</UserControl>
C#:
private void TestCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Test Command", "Test", MessageBoxButton.OK,
MessageBoxImage.Information);
}
private void TestCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
So the question is, what hidden factors can cause a CommandBinding
to fail silently? How do you even debug this? Why would I see completely different behavior between a Button
and a MenuItem
for the same command binding in the same control? Is it because the ContextMenu
is a resource? But in my test code, it's a resource and everything works.
UPDATE:
Another solution^Wworkaround: Explicitly set the MenuItem.PlacementTarget
to the ContextMenu
. Huh.