Intersoft ClientUI Documentation
Hybrid Commands

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. This is consistently implemented in ClientUI which brings the entire commanding infrastructure to the Silverlight platform. To learn more about the commanding pattern, see Commanding Overview.

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.

The HybridRoutedCommand introduces a more intuitive commanding pattern by adding status querying capability on the top of execute querying mechanism.

This topic contains the following sections:

Hybrid Routed Commands

Hybrid routed command is built on the top of routed command model that supports the commanding semantics such as the command, the command source, the command target, and the command binding. In addition, hybrid routed command exposes its own classes and object model to support additional features which includes HybridRoutedCommand, HybridCommandManager and a HybridCommandBinding class.

The HybridRoutedCommand class is derived from RoutedUICommand, and extended with IHybridCommand interface which expose two members, CanQueryStatus and QueryStatus, which are explained later in this topic.

You can use HybridRoutedCommand in the same way as you would do in RoutedCommand. The following code example shows how to setup a tool bar button to execute a HybridRoutedCommand.

XAML
Copy Code
<Grid x:Name="LayoutRoot">

    <Intersoft:CommandManager.CommandBindings>
        <Intersoft:CommandBindingCollection>
            <Intersoft:CommandBinding Command="Commands:EditingCommands.Bold"
                                      CanExecute="BoldCmdCanExecute"
                                      Executed="BoldCmdExecuted"/>
            
            <Intersoft:HybridCommandBinding Command="Commands:EditingCommands.Bold"
                                            CanExecute="BoldCmdCanExecute"
                                            Executed="BoldCmdExecuted"/>

        </Intersoft:CommandBindingCollection>
    </Intersoft:CommandManager.CommandBindings>
    
    <Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom">
        <Intersoft:UXToolBar Name="toolBar1" Intersoft:DockPanel.Dock="Top">
            <Intersoft:UXToolGroup>
                <Intersoft:UXToolBarButton Name="btn_Bold" Command="Commands:EditingCommands.Bold" DisplayMode="Image" Icon="../Images/BoldHS.png" ToolTipService.ToolTip="Bold"/>
                <Intersoft:UXToolBarButton Name="btn_Italic" Command="Commands:EditingCommands.Italic" DisplayMode="Image" Icon="../Images/ItalicHS.png" ToolTipService.ToolTip="Italic"/>
            </Intersoft:UXToolGroup>
        </Intersoft:UXToolBar>
        <Intersoft:UXTextBox Name="textBox1" Text="Type your text here..." Intersoft:DockPanel.IsFillElement="True" />
    </Intersoft:DockPanel>
</Grid>

As shown in the above example, the standard CommandBinding is required in addition to the HybridCommandBinding definition because the hybrid routed command is fundamentally built upon the routed command model.

The following code example shows the event handler for the CanExecute and Executed routed event for the CommandBinding associated to the Bold command.

C#
Copy Code
private void BoldCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

private void BoldCmdExecuted(object sender, ExecutedRoutedEventArgs e)
{
    string command = ((RoutedCommand)e.Command).Name;
    string target = ((FrameworkElement)e.OriginalSource).Name;

    MessageBox.Show("The " + command + " command has been invoked on target object " + target);
}

A version of hybrid command that supports MVVM Pattern is also provided. Using HybridDelegateCommand, you can define the command in the view model and bind it to the view. For more information about using command with MVVM Pattern, see MVVM Pattern Overview.

Introducing CanQueryStatus and QueryStatus

As briefly described in the previous section, hybrid command model introduces status querying capability in addition to the execute query. The status query is particularly useful for scenarios that require an alternate user interface state such as a toggle button in text editor.

Using the text editor scenario, the editing commands such as Bold and Italic should become checked or unchecked based on the current selection in the text editor. This behavior is added on top of the automatic state synchronization whereby the editing commands should become disabled if there is no selection in the text editor.

Hybrid routed command model is designed to address this particular requirements which makes it easier and simple to implement the alternate state query mechanism using the commanding semantics.

The status query concept can be categorized into the following sections.

CanQueryStatus Concept

HybridCommandManager exposes CanQueryStatus routed event to provide a mechanism to determine whether a command can query the status of its command target. The instance CanQueryStatus event is also available in the HybridCommandBinding class. The CanQueryStatus routed event sent a CanQueryStatusEventArgs as the event data when the routed event is raised.

The event data in CanQueryStatusEventArgs contains three main properties:

When a command is determined to support query status, you set the value of the CanQueryStatus property in the event data to true. The QueryStatus event will be raised according to the value of the CanQueryStatus property.

QueryStatus Concept

Similar to the CanExecute and Executed concept in routed command model, the hybrid command model follows the same semantics. The QueryStatus event will be raised only when the CanQueryStatus property in the event data is set to true.

When raised, the QueryStatus sent a QueryStatusEventArgs as the event data to the delegate that handles the routed event. The event data contains a Command property that identifies the action being executed and a QueryParameter property that represents the QueryStatusParameter object of which custom data will be sent to the command sources.

The QueryStatusParameter exposes two members discussed in the following:

The fundamental of query status concept in hybrid command model is basically a mechanism that allows you to pass the value of certain data, often the status of the command target, back to the command source. This allows the command source to be notified of the status and then appropriately perform an action based on the dispatched status.

For example, a UXToggleButton recognizes the Value property of a hybrid routed comand that bound to it. When the UXToggleButton is notified that the Value in the event data is true, it will automatically set its CheckedState property to true thus makes the button appear as checked in the user interface.

Supported Controls

For the hybrid routed command to be useful, there has to be command sources that implement specific behaviors and features related to the Value given in the QueryStatusParameter event data.

Many command-nature user interface controls in ClientUI support hybrid command model, such as all the button variants like UXButton, UXToggleButton, UXHyperlinkButton, UXNavigationButton and menu variants like UXMenuItem, UXStackItem and more.

Most of the controls mentioned above dispatch the Value of the event data and inspect if it has a true value. In such condition, the IsChecked property of these controls will be set to true, thus provides automatic synchronization for the alternate user interface state that based on commanding semantics.

Example

The hybrid routed command helps you elegantly address numerous challenges in UI programming. It is particularly useful in scenarios where an alternate user interface state is required to be updated according to the status of the command target. The commanding user interface in a text editing application describes this particular requirement and is the simplest way to understand how hybrid routed command works.

In a typical text editing application, the formatting commands such as Bold and Italic requires three state user interface pattern to properly represent the validity and the state of the command. Specifically, this scenario requires the user interface to be implemented in the following ways:

The following illustration describes the workflow of the formatting command in a typical text editing application.

 

The following code example shows how to setup the tool bar button and the hybrid routed command to achieve the user interface requirements such as discussed in the above illustration.

XAML
Copy Code
<Grid x:Name="LayoutRoot">

    <Intersoft:CommandManager.CommandBindings>
        <Intersoft:CommandBindingCollection>
            <Intersoft:CommandBinding Command="Commands:EditingCommands.Bold"
                                      CanExecute="BoldCmdCanExecute"
                                      Executed="BoldCmdExecuted"/>

            <Intersoft:HybridCommandBinding Command="Commands:EditingCommands.Bold"
                                            CanExecute="BoldCmdCanExecute"
                                            Executed="BoldCmdExecuted"
                                            CanQueryStatus="BoldCmdCanQueryStatus"
                                            QueryStatus="BoldCmdQueryStatus"/>

        </Intersoft:CommandBindingCollection>
    </Intersoft:CommandManager.CommandBindings>

    <Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom">
        <Intersoft:UXToolBar Name="toolBar1" Intersoft:DockPanel.Dock="Top">
            <Intersoft:UXToolGroup>
                <Intersoft:UXToolBarButton Command="Commands:EditingCommands.Bold" 
                                           IsToggleButton="True" DisplayMode="Image" Icon="../Images/BoldHS.png"/>
            </Intersoft:UXToolGroup>
        </Intersoft:UXToolBar>
        <RichTextBox Name="textBox1" Intersoft:DockPanel.IsFillElement="True">
            <Paragraph>
                <Run Text="Type your text here..."/>
            </Paragraph>
        </RichTextBox>
    </Intersoft:DockPanel>
</Grid>

The following code example shows the event handler for CanQueryStatus and QueryStatus routed event for the HybridCommandBinding associated to the Bold command.

C#
Copy Code
 private void BoldCmdCanQueryStatus(object sender, CanQueryStatusRoutedEventArgs e)
 {
     e.CanQueryStatus = true;
 }

 private void BoldCmdQueryStatus(object sender, QueryStatusRoutedEventArgs e)
 {
     if (e.Command == EditingCommands.Bold)
     {
         // notifies the current bold status to the command source
         // that bound to the Bold command.

         e.QueryParameter.Value = (FontWeight)textBox1.Selection.
             GetPropertyValue(Run.FontWeightProperty) == FontWeights.Bold;
     }
 }

For a complete example of how to implement a hybrid routed command, see How-to: Implement a HybridRoutedCommand.

Customizing the Behavior When a Command Cannot Execute

In addition to the status query capability, a hybrid routed command provides a built-in option to customize the command source behavior when a command cannot execute.

There are three possible options for CannotExecuteBehavior:

The following code shows how to define the NoExecuteBehavior of a hybrid command to use Collapsed mode so that the tool bar button will be hidden when the command cannot execute.

C#
Copy Code
private static readonly HybridRoutedCommand BoldCommand =
     new HybridRoutedCommand("Bold", "Bold", Intersoft.Client.Framework.NoExecuteBehavior.Collapsed, typeof(EditingCommands));

Alternatively, you can also set the NoExecuteBehavior on the command source independently such as on a particular tool bar button, which is shown in the following example.

XAML
Copy Code
<Intersoft:UXToolBarButton Name="btn_Bold" 
                           Command="Commands:EditingCommands.Bold" 
                           CommandCannotExecute="Collapsed"
                           ... />

Automatically Bind Command Properties to UI 

Although a command can be identified through its Name, the user interface often requires a more user-friendly text that describes the command. RoutedUICommand implements Text property to describe the text that should appear in the command sources that bound to the command.

HybridRoutedCommand extends the RoutedUICommand further by introducing an Image property to allow a command to be consistently represented by an identical image throughout the entire application. For examples, the commands such as New, Open and Save are often represented by the same icon throughout the application's user interface.

When a HybridRoutedCommand is bound to a command source that supports image content presentation, and that the AutoBindUI property of the HybridRoutedCommand is set to true, the command source will automatically assign the Image and Text of the hybrid command to the user interface. This feature is useful in the way it eliminates the need to define the text and icon in the user interface controls repetitively. To learn more about ClientUI controls that support image content presentation, see Content Model Overview.

The following code shows how to define a hybrid routed command with predefined Text and Image with the AutoBindUI feature enabled.

C#
Copy Code
private static readonly HybridRoutedCommand BoldCommand =
    new HybridRoutedCommand(
        "Toggle Bold", // Text
        "Bold", // Name
        new BitmapImage(new Uri("/images/BoldHS.png")), // Image
        Intersoft.Client.Framework.NoExecuteBehavior.Collapsed, // NoExecuteBehavior
        true, // AutoBindUI
        typeof(EditingCommands)); // Owner type

Step-by-step Walkthroughs

To learn more on how routed command and hybrid routed command can be used to address UI development challenges in step-by-step guides, see the following walkthroughs:

Walkthrough: Create Consistent UI for Rich Text Editor using Routed Command 

Walkthrough: Create Windows 7 Explorer UI using Hybrid Command 

See Also

Other Resources