Friday, April 26, 2013

WPF routed events and commands


When controls are added to a form, the event gets hooked up to the XAML markup and the handlers are added to the code behind. This should also be similar. When you right click on InitializeComponent method and go to definition, the editor will display the generated code file and you can see the routed event handlers added.
Each of the elements in the form are declared as a hierarchy of element forms which is called the logical tree. Most WPF controls are either ItemControls or ContentControls and they can have child elements.
Routed events get routed primarily on the visual tree. They support a routing strategy of Bubble, Tunnel or Direct. Bubble is the most common and events propagate up the visual tree. Tunnel goes in the other direction starting at the root and going down the leaf. Direct events behave like normal events and are handled only by the delegate attached to the event.
To walkthrough how a button click event is processed, we go through the following steps. A user will initiate a click event with a MouseLeftButtonDown event that happens inside the Image element. That event tunnels down from the root to the Image. If no handlers set the Handled flag to true for the preview event, the event then bubbles up from the image to the button. The button handles the event, set the Handled flag to true, and raises its own click event. Even when writing custom composite controls, the button handles these events to which the template is attached. In order to enable elements to handle events that are declared in a different element, you can attach events by specifying the element and the event in the markup.
Routed commands give a specific mechanism for hooking up UI controls such as toolbar buttons and menu items to handlers without introducing a lot of tight coupling or repetitive code in the application. Among the advantages of using routed commands as opposed to regular event handlers, the first advantage is that the source elements can be decoupled from the command targets. They do not need direct references to one another. Secondly, the commands will automatically enable or disable all associated UI controls when the handler indicates the command is disabled. Lastly, commands enable you to associate keyboard shortcuts and other forms of input gestures to invoke the command.

Commands are specified with the command property on the control. The command property is supported by a number of controls such as MenuItem, button, RadioButton, CheckBox, hyperlink, and a number of other controls. CommandBinding is specified for an element that acts as the event handler. The CanExecute and Executed properties of a command binding point to methods in the codebehind. The main thing here is that who calls whom is not important.
The CanExecute is called to determine whether or not the command should be enabled. When the executed method is set and the CanExecute is missing, the default behaviour is that the command is enabled.

To make this more concrete and to quickly see the benefits of routed commands, visualize a text box with controls that cuts and paste any selected text between two text boxes. The conventional approach would be to define the click handler and reference the two text boxes and call appropriate clipboard actions and this becomes harder and messier when the control is deep inside a custom control. Instead we could just specify a builtin command to do the same. After you select some text in one of the text boxes, the tool bar button becomes enabled. It could work for any text box anywhere in the UI. Under the covers, these routed commands use routed events to route messages between the command invokers and the command handlers. Once a single command handler is invoked, no other handlers will be called.

There are five builtin command classes in WPF and these are Application Commands, NavigationCommands, EditingCommands, MediaCommands, ComponentCommands etc. RoutedCommands implement the ICommand interface.

Courtesy: MSDN magazine article by Brian Noyes.

No comments:

Post a Comment