When developing a real-world application in Windows Forms .NET, you usually have multiple menus, tool bars, ribbons, context menus, etc. The challenge here is to provide central handlers to perform actions (e.g. an action to open a file) that came from various sources (e.g. the user clicks a menu item, or a tool bar item).
Usually you call this "command routing" or "event bubbling".
This article introduces a small command routing library that contains code that I extracted from one of our commercial products.
Past, Present and Future of Command Routing
Following is a short overview of some of the solutions of the past, the present and the (my) future.
In the pre-.NET days, there were the Microsoft Foundation Classes (MFC) that came with what they call "Command Routing".
In MFC's command routing, the framework was responsible for correctly dispatching to the correct handler. In the handler, you could specify (among other things):
- Whether the command's visual representation (a button, a menu item, ...) is displayed in enabled or disabled state.
- The action to perform when the command is being executed.
The dispatching took place automatically, depending on the current focused window.
.NET Windows Forms
Now when Windows Forms appeared, they completely lacked this command routing framework.
Therefore I developed my own minimal version that is nearly-bug-free for some projects. You can download the library together with an example project at the top of this article.
There are different approaches by other developers to solve the lack of command routing in Windows Forms. I found the following ones through some Googling:
Windows Presentation Foundation (WPF)
To be honest, I do have no practical experiences in WPF.
From what I do understand, WPF does have very decent command routing. Therefore I tried to investigate whether it would be possible to extract parts of the WPF command routing and use it in Windows Forms. Unfortunately, I failed and ended with the solution you can download in this article. (Here is a German discussion about that topic.)
The Library and the Example Application
The main class being responsible for the command routing is the
UICommandRoutingEngine class. Usually you create one instance per (main) form.
Both the (main) form and all user controls that want to be part of the event bubbling chain/tree do implement the
IUICommandRoutingTarget interface and register themselves in the command routing engine instance by calling the
The interface being implemented by the (main) form and the controls has the following members:
public interface IUICommandRoutingTarget
ref bool isEnabled,
UICommandEventArgs args );
UICommandEventArgs args );
The command routing engine is using these methods to query a control/form for the state of a command as well as to tell the control to actually execute a specific function.
An implementing form/control only handles those commands that it is actually responsible for. All other command are ignored by returning
UICommandResultInformation.ContinueRouting which tells the engine to continue bubbling the event to the parent in the hierarchy.
Probably you'll get into the ideas of the library fastest when looking at the example application that ships with the source download.
The Example Application
In the example application, there is one main form which implements the
IUICommandRoutingTarget interface and two user controls that both implement the
IUICommandRoutingTarget interface, too.
When running the application, you see the tool bar buttons getting enabled and disabled as you change the focus between the text boxes and entering/modifying text.
This article introduced a small command routing library together with an example Windows Forms application.
While the command routing library should be nearly bug free, the example application still contains some issues like buttons working on the wrong textbox. I will improve that in the future, I do hope that it still helps you to show you some of the ideas I had when developing the library.
Of course I would be very happy if you contribute fixes, additions and enhancements to the library. To ask questions, suggest features or provide other comments, please use the comments section at the bottom of this article.
- 2010-03-14 - First release to CodeProject