Bassem Mohsen's Programming Blog

"High thoughts must have high language." —Aristophanes

  • The Author

    Bassem Mohsen - Freelance Windows and
    Web application developer. Technical writer. 24 yo. Based in Cairo, Egypt.

  • MCTS certification logo

Fast Paste

Posted by Bassem Mohsen on May 10, 2011


Click here to download the source code and binaries of the Fast Paste project.
This project uses icons from the FamFamFam free icon library.

Introduction

People responsible for email response handling often have a set of commonly used sentences that they paste into their response messages. The WPF commanding system gave me an idea of a simple text editor that can help these people do their job faster. This application was built primarily to explore the commanding feature of WPF.

Using the Program

Fast Paste window

Most of the program commands can be invoked either from the top menu or from the toolbar buttons or using key gestures. For example to invoke the ‘open document’ command you select File > Open… or you use the toolbar button with the folder icon or you use the key gesture Ctrl+O. To paste the predefined string number 5 you select Edit > Paste Predefined > string 5 or you use the ‘5’ toolbar button or you use the key gesture Ctrl+5. Predefined strings come from a file ‘Strings.txt’ in the program’s working directory.

Program Architecture

The DocumentManager class contains methods for opening and saving documents, and methods for editing the document text.
The EditorWindow class handles the user input and forwards most of the user commands to the DocumentManager class.
The CustomCommands static class contains the definitions of the commands that are needed by the program and not predefined in the .NET Framework.
The StringManager class wraps the array of predefined strings loaded from ‘Strings.txt’.

Cut, Copy and, Paste Commands – The Framework Does It All!

WPF provides static objects to represent the cut, copy, and paste commands. These objects are available through the static properties of the ApplicationCommands class: ApplicationCommands.Cut, ApplicationCommands.Copy, ApplicationCommands.Paste. WPF also associated the key gestures Ctrl+X, Ctrl+C, and Ctrl+V to the cut, copy, and paste commands respectively.

The functionality to handle these commands is built into the TextBox control. So you do not have to do anything for TextBoxes in your application to support cutting, copying, and pasting using key gestures.

In my application, I wanted to give the user more options to invoke the cut, copy, and paste commands. So I provided menu items and toolbar buttons for invoking these commands. This was as simple as adding the Command="ApplicationCommands.*" attribute to the Button and MenuItem controls.

<Button Command="ApplicationCommands.Cut" …

<Button Command="ApplicationCommands.Copy" …

<Button Command="ApplicationCommands.Paste" …

<MenuItem Command="ApplicationCommands.Cut" />

<MenuItem Command="ApplicationCommands.Copy" />

<MenuItem Command="ApplicationCommands.Paste" />

CommandBinding and Implementing the Command Handlers Yourself

Usually, you have to write the logic that handles the command yourself. You associate the command to the method that handles the command using a CommandBinding object. This CommandBinding object should be added to the CommandBindings collection of the command source or one of its ancestors.

To handle the ApplicationCommands.New command, I added the following method to the code behind (note the method signature)

private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

    _documentManager.CreateNew();

}

And in the XAML file, I added a CommandBinding to the CommandBindings collection of the Window class

<Window.CommandBindings>

    <CommandBinding Command="ApplicationCommands.New" Executed="NewCommand_Executed" />

    …

</Window.CommandBindings>

Associating Input Gestures With Commands

MouseBinding and KeyBinding objects (both inherited from InputBinding) can be used to associate input gestures with commands. InputBinding objects are added to the InputBindings collection of a UIElement.

For example to associate the CopyAll command with the key gesture Ctrl+Shift+C I added a KeyBinding objects to the KeyBindings collection of the Window class.

<Window.InputBindings>

    <KeyBinding Command="local:CustomCommands.CopyAll" Key="C"Modifiers="Control+Shift" />

    …

</Window.InputBindings>

Custom Commands

If the .NET Framework does not have a command the suits your need, you can define your own command. You do that by instantiating the class RoutedUICommand. It is a good idea to expose your command object through a static property to make sure that only one instance of your command exists.

Here is how I defined the CopyAll command

private static RoutedUICommand _copyAll = new RoutedUICommand(
    "Copy All", "Copy All", typeof(CustomCommands));

public static RoutedUICommand CopyAll

{

    get

    {

        return _copyAll;

    }

}

Using Command Parameters

You can pass data from the command source to the command handler. The common command sources: Button, MenuItem, and InputBinding support the CommandParameter property. The value of CommandParameter is passed to the command handler and can be retrieved using the ExecutedRoutedEventArgs.Parameter property.

Here is how I passed the index of the predefined string to be pasted from the command source

<KeyBinding Command="local:CustomCommands.PastePredefined" CommandParameter="6" Key="D6"
            Modifiers="Control" />

<Button Command="local:CustomCommands.PastePredefined" CommandParameter="6">6</Button>

And here is how I retrieved and used it in the command handler

private void PastePredefinedCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

    int stringIndex = int.Parse(e.Parameter.ToString());

    _documentManager.PastePredefinedString(stringIndex);

 

    e.Handled = true;

}

Enabling and Disabling Commands

The CommandBinding.CanExecute event is raised to check whether the command associated with the CommandBinding can be executed. You can handle this event to provide the logic that determines whether the command can be executed. In your event handler you set CanExecuteRoutedEventArgs.CanExecute to true to enable the command and you set it to false to disable the command.

In my application, I wanted the CopyAll command to be enabled only when theTextBox is not empty. So I registered an event handler for the CommandBinding.CanExecute event.

<CommandBinding Command="local:CustomCommands.CopyAll" Executed="CopyAllCommand_Executed"

                CanExecute="CopyAllCommand_CanExecute" />

And in the event handler, I set CanExecuteRoutedEventArgs.CanExecute to enable or disable the command based on my condition.

private void CopyAllCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)

{

    if (theTextBox != null// The CanExecute event is raised before the TextBox object is created.

        e.CanExecute = !string.IsNullOrEmpty(theTextBox.Text);

}

Click here to download the source code and binaries of the Fast Paste project.
This project uses icons from the FamFamFam free icon library.

Leave a comment