0

I have a RoutedCommand defined like so:

public static class Commands
{
    /// <summary>
    /// Represents the Foo feature of the program.
    /// </summary>
    public static readonly RoutedCommand Foo = new RoutedCommand("Foo", typeof(Window1));
}

I then have a user control with the command defined like so:

<UserControl.CommandBindings>
    <CommandBinding Command="{x:Static local:Commands.Foo}" Executed="CommandBinding_Executed"/>    
</UserControl.CommandBindings>
<UserControl.InputBindings>
    <KeyBinding Command="{x:Static local:Commands.Foo}" Modifiers="Control"  Key="Space"></KeyBinding>
</UserControl.InputBindings>

and handled in code like so! (against my usercontrol class)

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
    MessageBox.Show("Executed from sub");
}

My custom user control is defined in my main window:

<local:UserControl1 x:Name="myC" Grid.Row="1" DataContext="{Binding ChildName}"></local:UserControl1>

and my main window also has it's own way of dealing with the Foo routed command:

CommandBindings.Add(new CommandBinding(Commands.Foo, new ExecutedRoutedEventHandler((x, y) => {

            MessageBox.Show("Something Happend from main window");

        })));

InputBindings.Add(new InputBinding(Commands.Foo, new KeyGesture(Key.P, ModifierKeys.Alt)));

Now, if the the command was fired from my user control I would expect the event to bubble up to the window IF the Handled property of the ExecutedRoutedEventArgs is set to false, and it is:

enter image description here

But only the messagebox from the user control will show, I would expect the message box from the handled event on the window to show after!

Thank you

William
  • 1,837
  • 2
  • 22
  • 36

2 Answers2

2

The handler of the CommandBinding.Executed event is invoked by CommandBinding.OnExecuted method that sets RoutedEventArgs.Handled to true right after the handler finishes. The method is internal and not virtual so there is not much that you can do about this behavior.

If you really want to make the parent handle the command, you can just invoke it from your handler. This will not be the same command, but it will cause the handler on the main window to fire.

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("Executed from sub");
        var rc = e.Command as RoutedCommand;
        var parentInput = FindParentInput();
        if (parentInput != null && rc != null)
        {
            rc.Execute(null, parentInput);
        }
    }

    private IInputElement FindParentInput()
    {
        DependencyObject element = this;
        while (element != null)
        {
            DependencyObject parent = VisualTreeHelper.GetParent(element);
            var input = parent as IInputElement;
            if (input != null)
                return input;
            element = parent;
        }
        return null;
    }

Note that if you try to use null for the second parameter, it will send the new command to this same UserControl again. That's why I've included the FindParentInput method that looks up the closest parent that implements `IInputElement' interface.

  • This is a related question describing another problem caused by the same behavior of `CommandBinding` http://stackoverflow.com/questions/2290142/can-i-have-multiple-commandbindings-for-the-same-command-on-the-same-control – Michael Domashchenko Nov 07 '15 at 17:20
0

You can do this simpler, it seems that all UIElements implement IInputElement so you should be OK with routing to the direct parent (tried this on my simple app and it works from my custom control back to the main window):

  private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
  {
     RoutedCommand c = e.Command as RoutedCommand;
     IInputElement parent = this.Parent as IInputElement;
     c.Execute(e.Parameter, parent);
  }
lutecki
  • 339
  • 4
  • 5