Commands, Input and the WPF - Command Source
(Page 4 of 4 )
The command source is the object that was used to invoke the command. It might be a user interface element, such as a button, hyperlink, or menu item. But it can also be an input gesture. Command sources all implement the ICommandSource interface, as shown in Example 4-20.
Example 4-20. ICommandSource
public interface ICommandSource {
ICommand Command { get; }
object CommandParameter { get; }
IInputElement CommandTarget { get; }
}
If you set theCommand property to a command object, the source will invoke this command when clicked, or in the case of an input gesture, when the user performs the relevant gesture.
TheCommandParameterproperty allows us to pass information to a command when it is invoked. For example, we could tell our hypotheticalAddToBasketcommand what we would like to add to the basket, as shown in Example 4-21.
Example 4-21. Passing a command parameter
<MenuItem Command="m:MyAppCommands.AddToBasketCommand"
CommandParameter="productId4823"
Header="Add to basket" />
The command handler can retrieve the parameter from theParameter property of theExecutedRoutedEventArgs, as Example 4-22 shows. (This example is a command handler for our hypotheticalAddToBasketCommand. The handler would be attached with a command binding as was shown in Example 4-16.)
Example 4-22. Retrieving a command parameter
void AddToBasketHandler(object sender, ExecutedRoutedEventArgs e) {
string productId = (string) e.Parameter;
...
}
Command parameters are slightly less useful if you plan to associate commands with keyboard shortcuts. Input bindings are command sources, so they also offer aCommandParameterproperty, but Example 4-23 shows the problem with this.
Example 4-23. Associating a command parameter with a shortcut
public Window1() {
InitializeComponent();
KeyBinding kb = new KeyBinding(MyAppCommands.AddToBasketCommand, Key.B,
ModifierKeys.Shift| ModifierKeys.Control);
kb.CommandParameter = "productId4299";
this.InputBindings.Add(kb);
}
This adds an input binding, associating the Ctrl-Shift-B shortcut with ourAddToBasketCommand. TheCommandParameterproperty of the binding will be passed to the command handler just as it is when the input source is a button or menu item. But of course, it will pass the same parameter every time, which limits the utility—you might just as well hardcode the value into the command handler. So in practice, you would normally use command parameters only for commands without a keyboard shortcut.
If you were building a real application with shopping-basket functionality, it would probably make more sense to use data binding rather than command parameters. If you arrange for the control that invokes the command to have its data context set to the data you require, the command handler can retrieve theDataContextof the command target, as Example 4-24 shows.
Example 4-24. Commands and data
void AddToBasketHandler(object sender, ExecutedRoutedEventArgs e) {
FrameworkElement source = (FrameworkElement) e.Source;
ProductInfo product = (ProductInfo) source.DataContext;
...
}
This technique has the benefit of working even when a keyboard shortcut is used. Chapter 6 explains data contexts.
The ICommandSourceinterface also offers aCommandTargetproperty. Although the interface defines this as a read-only property, all of the classes that implement this interface in WPF add a setter, enabling you to set the target explicitly. If you don’t set this, the command target will typically be the element with the input focus (although, as we’ll see later, there are some subtle exceptions).CommandTargetlets you ensure that a particular command source directs the command to a specific target, regardless of where the input focus may be. As an example of where you might use this, consider an application that uses aRichTextBoxas part of a data template (introduced in Chapter 1)—you might use this to allow the user to add annotations to data items in a list. If you provided a set of buttons right next to theRichTextBoxto invoke commands such asToggleBoldorToggleItalic, you would want these to be applicable only to theRichTextBoxthey are next to. It would be confusing to the user if she clicked on one of these while the focus happened to be elsewhere in her application. By specifying a command target, you ensure that the command only ever goes where it is meant to go.
Please check back next week for the conclusion to this article.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
|
This article is excerpted from Programming WPF, Second Edition, written by Chris Sells and Ian Griffiths (O'Reilly, 2007; ISBN: 0596510373). Check it out today at your favorite bookstore. Buy this book now.
|
|