ClientUI Framework provides a powerful commanding framework that enables developers to leverage the commanding pattern to use in their applications. The commanding framework in ClientUI supports the routed command concept available in WPF, as well as several advanced command types which will be discussed later in this topic.
To learn more about the concepts and frameworks available in ClientUI, see ClientUI Architecture Overview.
This overview describes the basic concepts of commanding, its benefits, how to use it and why you should use commands in your application whenever possible.
Commanding: The Basics
Command is mainly used to separate the semantics and the object that invokes a command from the logic that executes the command. This allows for multiple and disparate sources to invoke the same command logic, and it allows the command logic to be customized for different targets.
The simplest form of a Command is an object that implements ICommand, which exposes CanExecute and Execute method. The command is then consumed in an application which provides a consistent pattern to query and execute the logic associated to the Command. This pattern is often referred as Commanding Pattern which has been around for a while.
With the advent of Windows Presentation Foundation (WPF), the commanding pattern has evolved into more advanced commands such as routed command and routed UI command, which take advantage of the robust visual tree model. The routed command model uses the event routing mechanism to notify the visual tree about the command being executed. For more information about event routing, see Routed Events Overview.
Developers find routed command to be more intuitive and easier to implement because a routed command can be generally consumed in various ways, either declaratively defined in the XAML or programmatically implemented using code.
The command is the action to be executed.
The command source is the object which invokes the command.
The command target is the object that the command is being executed on.
The command binding is the object which maps the command logic to the command.
A routed command is typically implemented through these processes: a RoutedCommand is initially associated to a control that implements ICommandSource such as UXButton, create a CommandBinding, and then create the event handlers which implement the logic for the RoutedCommand.
The following code example illustrates the big picture of these processes and shows how the routed command and command binding can be easily defined in XAML.
To see more walkthrough and examples of commanding, see Commanding How-to Topics.
Why Use Commands?
The commanding pattern, specifically the routed command model, provides solid infrastructure and flexible ways for developers to create consistent and reliable user experiences. Consequently, you should consider using commands in your application design whenever possible.
There are several advantages to use the commanding pattern in your application:
- Loosely-coupled implementation between the View (UI) and the command logic
Separating the command logic from the view helps maintain your code clean, test-able and easily extensible.
- High reusability
Unlike traditional UI programming, the routed command model enables you to write the command logic once, and reuse the command to any number of controls in the view.
- Consistent user experience
Routed commands help you create user interface that works consistently and reliably. Unlike traditional UI programming that requires you to manually write plumbing codes to disable or enable a control, routed command automatically enable or disable the controls that bound to it according to the value of the CanExecute property in the event data. In addition, this behavior is also applied to the input devices that associated to the command, which creates a consistent user experiences in the way that keyboard access and mouse would not be able to execute the command when its CanExecute value is false. The input handling is represented by an InputBinding, which is discussed later in this topic.
- Better stability and easier to extend
With routed commands, your application produces less issues and unexpected errors. This is possible because the command logic can be easily refactored and centralized in a way that makes the code testable. When you need to add new user interface that exposes the same command, you can simply assign the RoutedCommand to the control in the XAML thus eliminate the need to duplicate the code used to handle the command logic.
- Solid foundation for the next-generation UI programming
Using commanding in your application enables you to leverage a number of modern application design pattern such as MVVM pattern, without the need to revamp your application architecture. The commanding pattern aligns perfectly with MVVM pattern in the perspective that both patterns emphasizes on separation of concerns, which specifically refers to loosely-coupled approach of UI development. The commanding usage with MVVM pattern is discussed later in this topic.
Commanding Support in ClientUI
Despite being a subset of WPF, Silverlight does not include routed command infrastructure in its core framework. Consequently, developers would not be able to build a rich user interface using the commanding pattern that similar to the WPF commanding. ClientUI provides developers with a comprehensive framework that implements a full specification of routed command infrastructure.
The following sections describe an overview of the commanding support in ClientUI.
Supports WPF-style Commanding
ClientUI provides a full set of class libraries that implement routed command according to the specification, mechanism and behaviors of WPF routed command. Some major libraries include CommandManager, CommandBinding, InputBinding, InputGesture, ICommandSource and a number of types to support the routed command infrastructure.
In addition, ClientUI also supports the tunneling version of the commanding routed events such as the PreviewCanExecute and PreviewExecuted, in addition to the CanExecute and Executed bubbling routed events. To learn more about routed events, see Routed Events Overview.
With ClientUI commanding framework, you can build application using unified XAML and code that target both Silverlight and WPF platform. For more information about unified development model with ClientUI, see Unified Development Model.
Includes a Variety of UI Controls that Support Commanding
For the routed command model to work efficiently, there must be user interface controls that implement ICommandSource interface to support and take advantage of the routed command. Because the routed command infrastructure is built into the ClientUI's framework, many of the command-nature controls such as UXButton, UXToolbarButton, UXSplitButton, UXHyperlinkButton, UXMenuItem and more, implement the ICommandSource interface enabling you to fully leverage the benefits of routed command.
Specifically, the ClientUI controls that implement ICommandSource interface, which are generally referred as command sources, exposes the members listed in the following:
- Command is the command to execute when the command source is invoked.
- CommandTarget is the object on which to execute the command. Note that the CommandTarget property on ICommandSource is only applicable when the ICommand is a RoutedCommand. If the CommandTarget is set on an ICommandSource and the corresponding command is not a RoutedCommand, the command target is ignored. If the CommandTarget is not set, the element with keyboard focus will be the command target.
- CommandParameter is a user-defined data type used to pass information to the handlers implementing the command.
Includes Predefined Command Library
ClientUI makes use of commanding extensively throughout its frameworks and user interface controls to create rich feature-sets that designed with commanding semantics. Features that use commanding semantics provides more flexible ways for developers to consume the feature and at the same time delivers more solid design that allows better scalability and easier to extend.
In addition, controls that are built with commanding semantics use loosely-coupled engineering that separates the actual logic implementation from the feature. Consequently, this allows a particular feature to be easily reused and consumed in ways that are not possible in traditional controls that do not leverage the commanding pattern.
The examples of frameworks in ClientUI that make use of commanding extensively are navigation framework and application framework. Several advanced controls like UXWindow, UXDesktop and UXDesktopDock make use of commanding extensively to create user experience that works consistently across the user interface elements. For example, when a window cannot be closed, the Close button in the title bar, the Close menu item in the context menu, and the Close feature in the task bar will be grayed out.
As the result of the comprehensive support for commanding, ClientUI includes a number of predefined command library that you can use directly, such as the BrowseBack, BrowseForward and Navigate for navigation commands and SetActive, Maximize, Close and more for windowing commands. The complete list of the predefined command library is described later in this topic.
Supports Advanced Routed Command
The routed command model introduced in WPF basically provides an automatic state synchronization between the command sources and the command through command binding. In WPF, the command source supports the IsEnabled synchronization based on the value of the CanExecute in the event data.
ClientUI extends the routed command model further by introducing hybrid routed command, a more advanced routed command that supports two kind of state synchronization behavior. In addition to the IsEnabled handling, HybridRoutedCommand can automatically synchronize the Visibility property of the command sources based on the value of the CanExecute in the event data. More details about HybridRoutedCommand, see Hybrid Commands.
There are a number of ways to implement routed command in your application. You can work with the commands in XAML, or register them using code. Depending on your requirements, you can use instance command handler or class command handler, which both of them are supported in the ClientUI commanding framework.
The following example shows how to setup the Cut button to execute the EditingCommands.Cut routed command when the button is clicked.
Similar to the objective in the previous example, the following example shows how to setup the routed command and binding using code.
In addition to instance command binding, the commanding framework in ClientUI also supports class command binding API which is available in the CommandManager class. The class command binding is particularly useful when you have a fairly large amount of commands to bind to the controls.
The following example shows how to use the RegisterClassCommandBinding method to register the command binding to a specific class.
Command Library in ClientUI
ClientUI makes use of commanding extensively throughout its frameworks and user interface controls to create rich feature-sets that designed with commanding semantics. Several key frameworks in ClientUI that make use of commanding extensively are navigation framework and application framework. Several advanced controls like UXWindow, UXDesktop and UXDesktopDock make use of commanding extensively to create user experience that works consistently across the user interface elements. For example, when a window cannot be closed, the Close button in the title bar, the Close menu item in the context menu, and the Close feature in the task bar will be grayed out.
ClientUI includes a number of predefined command library that you can use directly such as described in the following list.
Using Commanding with MVVM Pattern
In addition to the full support for routed command model, ClientUI extends its commanding framework further to support MVVM pattern without trading off the benefits of routed command model.
Specifically, ClientUI provides DelegateCommand, a specialized command object that can be used to handle a delegate directly in the view model, and still can be bound to the view through binding. To learn more about using commanding with MVVM pattern, see MVVM Pattern Overview.