The Truth about Routed Commands Routing

In my article on Routed Events and Commands in the September MSDN Magazine, I made a quick reference to a very subtle, confusing, and misunderstood aspect of how routed commands are actually routed. It was only a brief reference because it was only made clear to me through some excellent tech review feedback from the Product Team (thanks Dwayne and Varsha!) a couple days before going to print, so I couldn’t add a big explanation without trashing the print flow for the magazine.

I had a question from a reader who is a well known WPF expert himself, so I figured I’d better expand my explanation.

The short simple answer if you don’t want to understand all the complexities of what is going on under the covers is this: Always put your command bindings on the root element (Window or Page) and your command binding will always be consulted. You can do this explicitly in the XAML, or you can inject it there through CommandManager.RegisterClassCommandBinding.

But if you want to deviate from that guidance, you really have to understand the following.

With WPF routed commands, routed events are used under the covers to dispatch calls to the command handlers both to determine when the command should be enabled, and to invoke the handling for that command when the command is invoked. For example, if I have a Save button in a toolbar, and I have a command binding at my Window root level, a routed event will be used to ask the CanExecute method of that binding if the button should be enabled. And then when the user clicks it, a routed event will be used to call the Executed method of the command binding.

Where things get confusing is if you try to place that command binding somewhere deeper in the visual tree because you have to have a good understanding of where the routed events are started and where all they flow to.

There are a lot of people that believe (myself included until Dwayne and Varsha from the product team showed me the light) that the routed events for commands flow from the focused element to the root of the visual tree with tunneling and bubbling events. That is really only a part of the picture.

The fact is that the routed events for a routed command ALWAYS are initially raised on the command invoker or source control, not the focused element. Any control that implements the ICommandSource interface can be a command source. This includes buttons (and checkboxes… anything deriving from ButtonBase), menu items, hyperlinks, and input bindings (i.e. keybinding) out of the box in WPF. These events follow the standard pattern for routed events in WPF – a tunneling event is routed down the visual tree from the rootto the target and then a bubbling event is routed up the visual tree from the target back to the root.

The focused element in the UI only gets the events routed to it if the command source is contained in a focus scope (the Toolbar). When that is the case, as the bubbling event reaches the focus scope boundary, the event is re-raised on the focused element.

So what is a focus scope? A focus scope is any container element that sets the FocusManager.IsFocusScope attached property to true. Toolbars and menus have this property set, so those are the main focus scopes you will deal with other than a Window or Page which is always the root focus scope, but you could easily create your own by setting that property to true on a container control.

So in my Save button example above, the flow looks like this when the button is clicked:

  • CommandManager.PreviewExecuted tunneling event raised on the Save button in the toolbar. This means it starts at the root element of the visual tree and tunnels down to the Save button through whatever element tree is in between.
  • CommandManager.Executed bubbling event raised on the Save button in the toolbar. This means the bubbling event flows from the button up to the root element of the Toolbar.
  • CommandManager.PreviewExecuted tunneling event raised on the focused element in the root UI.
  • CommandManager.Executed bubbling event raised on the focused element in the root UI.

To make it even more concrete, I wrote a little form whose element tree looks like this with several sources of the Cut command:

<Windowx:Class="CommandFlow.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"><DockPanel><ToolBarDockPanel.Dock="Top"Height="30"><ButtonWidth="75"Height="25"Command="Cut">CutButton>ToolBar><StackPanel><ButtonWidth="75"Height="25"Command="Cut">CutButton><TextBoxWidth="150"Height="25"/>StackPanel>DockPanel>Window>

I then added attached event handlers for the PreviewExecuted and Executed events to each element in the tree and did a Debug.WriteLine so it would be very clear where the Executed events were flowing. I then ran it, put the focus in the Textbox, and clicked the button in the toolbar. The result is below.

Window PreviewExecuted Called

DockPanel PreviewExecuted Called

Toolbar PreviewExecuted Called

Toolbar button PreviewExecuted Called

Toolbar buttonExecuted Called

Window PreviewExecuted Called

DockPanel PreviewExecuted Called

StackPanel PreviewExecuted Called

Textbox PreviewExecuted Called

As you can see, a tunneling (Preview) event works its way down from the root element to the Toolbar button that is the command source, followed by a bubbling event back up. The important thing to notice here though, which is where the confusion about howthe focused element is involved, is that the bubbling event seems to have stopped after firing on the toolbar button, and then a new tunneling event is raised which tunnels down to the Textbox and ends.

What is happening is that the Toolbar is actually handling the bubbling Executed event (Handled = true), which stops the bubbling process. The CommandManager then re-raises the event on the focused element (Textbox) and a Preview event tunnels down to it. The Textbox has an internal handler for the Cut command, so that is why nothing bubbles back up from there.

WithFocusScope

If that wasn’t confusing enough, you then also have to look at what goes on for command enabling. The CanExecute part of ICommand has a similar pair of tunneling and bubbling events that fire. They too always get raised on command source controls first. These events are triggered by things that change the focus of the UI. If there is more than one command source, each one gets consulted in turn. Then the path to the focused element in the UI gets consulted. Below is the sequence of events after the UI is up and idle, then I click in the Textbox to set the focus there.

Window Preview Can Execute Called

DockPanel Preview Can Execute Called

StackPanel Preview Can Execute Called

Window button Preview Can Execute Called

Window button Can Execute Called

StackPanel Can Execute Called

DockPanel Can Execute Called

Window Can Execute Called

Window Preview Can Execute Called

DockPanel Preview Can Execute Called

Toolbar Preview Can Execute Called

Toolbar button Preview Can Execute Called

Toolbar button Can Execute Called

Window Preview Can Execute Called

DockPanel Preview Can Execute Called

StackPanel Preview Can Execute Called

Textbox Preview Can Execute Called

So the bottom line to me is this: it is very difficult to explain and understand where the events are flowing in even a simple UI, let alone a very complex one. Trying to rationalize that in your development process to put command bindings anywhere except on the root element is the path to command routing hell. You are better off just always placing your command bindings on the root element, or if you don’t want to do that, consider using Prism Commands which get the handlers decoupled from the visual tree and the focus. If you are a control developer, and you need to handle commands (such as Cut) that are inherently coupled to whether your control has the focus, then putting command bindings in your control will also make sense.

I hope that helps to clarify the magic that is happening under the covers of routed command routing.