Search code examples
c#wpfcommandrouted-commandstunneling

RoutedCommands that use tunneling instead of bubbling


I have a custom control (MyControl) that exposes a custom command. I want the parent Window to be able to invoke this command, and all MyControls should react to it.

I have added the command to MyControl's CommandBindings collection, which also provides a CanExecute callback that always returns true.

My problem is that a menu item that invokes this command never gets enabled. I'm presuming this is because the menu is above the MyControls in the visual tree, but to be honest I'm a little fuzzy on how RoutedUICommand's scope works exactly.

Can someone clarify what I'm doing wrong, or if this is even possible?


Solution

  • Yes, the point is that the CommandBinding for your custom command is at a lower that your menu item in the visual tree. From msdn

    When the CanExecute method on a RoutedCommand is called, the PreviewCanExecute event is raised on the command target. If the event is not handled, the CanExecute event is raised. If the command target has a CommandBinding for the command, the CanExecute handler for that CommandBinding is called. If the command target does not have a CommandBinding for the command, the CanExecute event bubbles up the element tree searching for an element that has a CommandBinding associated with the command.

    A very good article about commands in at this link.

    Anyway you can use CommandTarget the command from your menu item such as

    <MenuItem Header="Click me"  Command="local:CommandClass.MyCustomCommand" CommandTarget="{Binding ElementName=myCustomCtrl}" />
    

    In this way a particular command source (the menu item) directs the command to the specific target (instance of the custom control).