Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Illustrated WPF phần 6 pot
Nội dung xem thử
Mô tả chi tiết
CHAPTER 9 ■ ROUTING EVENTS AND COMMANDS
238
Commands have, as part of their architecture, a way for the programmer to specify under what
circumstances a command should be available and when it should not be available. You can see this in
action in the buttons in the example program. Figure 9-13 shows that the buttons acting as the sources
for the Cut and Paste commands are automatically enabled or disabled appropriately for their clipboard
functions.
• In the first screenshot, neither of the buttons is enabled. This is because there is
no selected text in the first TextBox for the Cut command to work on and no text
on the system clipboard to be pasted by the Paste command.
• In the second screenshot, where there is selected text in the first TextBox, the Cut
button has automatically become enabled.
• In the third screenshot, the Cut button has been clicked, deleting the text from the
first TextBox and placing it on the system clipboard.
− Since there’s no longer any selected text in the first TextBox, the Cut button
becomes disabled.
− Since there’s now text on the system clipboard, the Paste button
automatically becomes enabled.
• Although you can’t see it in the figure, the keyboard shortcuts also work as you’d
expect.
− When the Cut button is enabled and the focus is on the first TextBox, you can
use the Ctrl+X keyboard shortcut to cut the text.
− When the Paste button is enabled and the focus is on the second TextBox, you
can use the Ctrl+V keyboard gesture to paste the text.
Notice that there is nothing explicitly in the code to create any of this behavior, and yet it does
the right things. The reason these work is that this functionality was built in to the controls, to hook up
with these predefined commands. The command architecture allows you to build similar functionality
into your own custom commands.
Figure 9-13. The Cut and Paste buttons automatically become enabled or disabled appropriately for the
conditions and their functions.
CHAPTER 9 ■ ROUTING EVENTS AND COMMANDS
239
The RoutedCommand Class
The key to the WPF command architecture is the RoutedCommand class. To create your own commands,
you’ll need to create an instance of this class, configure it, and bind it to the controls with which you
want to use it, as you’ll see in the next section.
You might be tempted to think that this class implements the actions that should be taken
when the command is invoked. It doesn’t. Its main job is to raise events that trigger actions. The
RoutedCommand class has two major methods, Execute and CanExecute.
• The Execute method is called when the command is invoked as the result of the
action of a command source.
− The Execute method, however, does not execute the code to implement the
command! Instead, it raises two routed events—PreviewExecuted and
Executed.
− These routed events traverse the tree to trigger the event handler that actually
performs the implementation of the command.
• The CanExecute method is called when a source wants to find out whether it’s
appropriate to make the command available.
− Like the Execute method, the CanExecute method also does not implement the
action it represents. It also raises two routed commands—PreviewCanExecute
and CanExecute.
− These routed commands traverse the tree to find the event handler that can
determine whether to make the command available.
There are also two other important members of the RoutedCommand class—CanExecuteChanged
and InputGestures. Figure 9-14 shows the important members of these classes. The RoutedUICommand
class derives from the RoutedCommand class and just adds a field named Text, which you can use to label
controls or elements triggered by the command.
CanExecuteChanged is a RoutedEvent that is raised when there are changes that might affect
whether the command should be available. These signal the command source that it should call the
CanExecute method to determine whether it’s appropriate to make the command available.
InputGestures is a property that returns the collection of input gestures associated with the
command.
Figure 9-14. The important members of the RoutedCommand class
CHAPTER 9 ■ ROUTING EVENTS AND COMMANDS
240
Creating Custom Commands
The previous example showed how to use WPF’s built-in commands with controls that have command
support built in. This is very powerful and can be a huge time-saver. Sometimes, however, you might
need to create your own custom commands. In this section, we’ll create a small program that has a
custom command called Reverse, which reverses a string in a TextBox.
Figure 9-15 illustrates the program and shows the states of the source and target. The Reverse
button is the command source of the Reverse command. The TextBox is the command target. The other
command source is the keyboard gesture Ctrl+R. When the command is executed, by either the button
or the keyboard gesture, the text in the TextBox is reversed, as shown in the figure. If there’s no text in the
TextBox, then the button and the keyboard gesture are disabled.
Figure 9-15. The window implementing the Reverse command
Figure 9-16 shows the structure you’ll need for implementing the Reverse command. You’ll
need to do the following things:
1. Create a new class that defines the command, including the input gestures.
2. Create the command handler methods to be invoked by the Executed and
CanExecute events.
3. Create a command binding to connect the command with the command handler
code
4. Connect the command source with the command.
Figure 9-16. The command structure for implementing the Reverse command
CHAPTER 9 ■ ROUTING EVENTS AND COMMANDS
241
First create the custom command inside a class called CommandReverse, which will create and
supply the command through a property. Microsoft uses this pattern in its built-in commands. You’ll
place this code in a separate file called ReverseCommand.cs. The important things to notice are the
following:
• The class creates a private variable called reverse, of type RoutedUICommand to
hold the new command.
• The command is supplied to the outside through the read only Reverse property.
• The constructor creates a new KeyGesture object that represents the Ctrl+R
keyboard shortcut, and adds it to an InputGesturesCollection, which will be
associated with the new command.
• The constructor then creates a new RoutedUICommand and assigns it to the private
variable.
using System;
using System.Windows.Input; // Required
namespace CommandReverse
{
public class ReverseCommand
{
private static RoutedUICommand reverse;
public static RoutedUICommand Reverse
{ get { return reverse; } }
static ReverseCommand()
{
InputGestureCollection gestures = new InputGestureCollection();
gestures.Add
( new KeyGesture(Key.R, ModifierKeys.Control, "Control-R"));
reverse = new RoutedUICommand
( "Reverse", "Reverse", typeof(ReverseCommand), gestures);
} ↑ ↑ ↑ ↑
} Description Name of The Type Registering Collection of
} the Command the Command InputGestures
Next, create the markup, which is just used to create the source and target objects. All the other
objects you’ll create in the code-behind. This makes the markup very simple, as shown here—just a
TextBox and a Button in a StackPanel:
<StackPanel>
<TextBox Name="txtBox" Margin="10,10"
FontWeight="Bold" Background="Aqua"/>
<Button Name="btnReverse" HorizontalAlignment="Center" Padding="10,3"
FontWeight="Bold" Margin="10,0"/>
</StackPanel>