#1,094 – Disabling Editing Operations in a TextBox

You can disable the cut/copy/paste features in a TextBox by handling the CommandManager.PreviewCanExecute event and checking for the associated editing commands.

TextBox has implicit command bindings to support cut, copy, and paste commands.  When the user executes one of these commands, using the context menu or a keyboard shortcut, the associated routed command is executed, with the TextBox as the source.  You can short-circuit the command by intercepting PreviewCanExecute and making sure that CanExecute returns false.

Markup:
        <TextBox Name="txtSomeText"
                 CommandManager.PreviewCanExecute="txtSomeText_PreviewCanExecute"
                 Width="220" Height="25" Margin="10"/>

Code-behind:

        private void txtSomeText_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if ((e.Command == ApplicationCommands.Cut) ||
                (e.Command == ApplicationCommands.Copy) ||
                (e.Command == ApplicationCommands.Paste))
            {
                e.Handled = true;
                e.CanExecute = false;
            }
        }

The editing functions are now disabled. The context menu in the TextBox shows the commands greyed out and corresponding keyboard shortcuts do nothing.

1094-001

#1,071 – How TextBox Reacts to Gaining Keyboard Focus

If you have an application with several TextBox controls, you’ll notice that the TextBox that currently has focus “lights up” by drawing a light blue border around the edge of the TextBox.

1071-001

The TextBox draws the blue border by setting up a trigger in its control template.  You can see the body of the control template by right-clicking the TextBox in Visual Studio from the design surface and selecting Edit Template, followed by Edit a Copy.

1071-002

When you do this, you’ll be asked to give the new copy a name (e.g. TextBoxStyle1).  You’ll then get the full body of the template in the XAML document.

Looking at this template, you’ll see a Trigger on the IsKeyboardFocused property that sets the value of the BorderBrush on a Border element.  It sets it to a static resource, which is defined earlier in the template (to a light blue color).

1071-002 1071-003

#949 – Add a Custom Dictionary for Spell Checking in a TextBox

The built-in spell checker in a TextBox uses a predefined dictionary to look up words.  This means that there may be words flagged as misspelled because they are not in the dictionary.
949-001

You can add a custom dictionary to WPF’s spell checker by creating a lexicon (.lex) file.  To create a custom dictionary, start by creating a .lex file in your project.

949-002

Add any custom words to your dictionary, one line at a time.

949-003

Set the Build Action of the .lex file to Resource.

949-004

In the .xaml file containing the TextBox element, define a namespace that refers to the system assembly.

        xmlns:sys="clr-namespace:System;assembly=system"

And set the SpellCheck.CustomDictionaries element using a Uri to refer to your dictionary.

        <TextBox Name="txtMyText" Margin="5" Height="100"
                 TextWrapping="Wrap"
                 VerticalScrollBarVisibility="Auto"
                 SpellCheck.IsEnabled="True">
            <SpellCheck.CustomDictionaries>
                <sys:Uri>pack://application:,,,/MyDictionary.lex</sys:Uri>
            </SpellCheck.CustomDictionaries>
        </TextBox>

The spell checker now recognizes your custom words.

949-005

#948 – Complete Example of Limiting TextBox Input

If you want to limit text allowed as input to a TextBox, a full strategy for checking text being input should include handling the PreviewKeyDown and PreviewTextInput events, as well as implementing a pasting handler.  Below is a full example that limits text input to alphabetic characters only.

        <TextBox Name="txtMyText" Margin="5" Height="100"
                 TextWrapping="Wrap"
                 AcceptsReturn="True"
                 VerticalScrollBarVisibility="Auto"
                 PreviewTextInput="TextBox_PreviewTextInput"
                 PreviewKeyDown="TextBox_PreviewKeyDown"/>

 

        public MainWindow()
        {
            this.InitializeComponent();
            DataObject.AddPastingHandler(txtMyText, PasteHandler);
        }

        private bool IsAlphabetic(string s)
        {
            Regex r = new Regex(@"^[a-zA-Z]+$");

            return r.IsMatch(s);
        }

        private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            // Prohibit non-alphabetic
            if (!IsAlphabetic(e.Text))
                e.Handled = true;
        }

        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            // Prohibit space
            if (e.Key == Key.Space)
                e.Handled = true;
        }

        private void PasteHandler(object sender, DataObjectPastingEventArgs e)
        {
            TextBox tb = sender as TextBox;
            bool textOK = false;

            if (e.DataObject.GetDataPresent(typeof(string)))
            {
                // Allow pasting only alphabetic
                string pasteText = e.DataObject.GetData(typeof(string)) as string;
                if (IsAlphabetic(pasteText))
                    textOK = true;
            }

            if (!textOK)
                e.CancelCommand();
        }

#947 – Intercepting Paste Operations in a TextBox

Because the TextBox control automatically supports copy/cut/paste functionality, you may want to intercept paste events to determine if the text to be pasted should be allowed.

You can intercept data being pasted into a TextBox using a pasting handler.  Within the body of the handler, you check the text to be pasted and optionally cancel the paste operation if the text should not be allowed.

You call DataObject.AddPastingHandler when your application starts, specifying the TextBox for which you want to intercept paste events.

        public MainWindow()
        {
            this.InitializeComponent();
            DataObject.AddPastingHandler(txtMyText, PasteHandler);
        }

In the pasting handler, you call the CancelCommand method to reject paste operations.

        private void PasteHandler(object sender, DataObjectPastingEventArgs e)
        {
            TextBox tb = sender as TextBox;
            bool textOK = false;

            if (e.DataObject.GetDataPresent(typeof(string)))
            {
                string pasteText = e.DataObject.GetData(typeof(string)) as string;
                Regex r = new Regex(@"^[a-zA-Z]+$");
                if (r.IsMatch(pasteText))
                    textOK = true;
            }

            if (!textOK)
                e.CancelCommand();
        }

#945 – A Strategy for Limiting Allowed Text in a TextBox

You can limit the text that a user enters into a TextBox by handling the PreviewTextInput event and setting the TextCompositionEventArgs.Handled property to true for characters that you do not want to allow as input.

The PreviewTextInput event will not give you access to every possible keystroke that you might want to use in limiting input.  It’s not fired, for example, when the user presses the spacebar.

You often will also want to handle the PreviewKeyDown event to block keystrokes that don’t trigger PreviewTextInput.

Finally, you may want to intercept Paste events on a TextBox, in order to filter out text that you don’t want a user to paste into the TextBox.

A full strategy for limiting user-entered text might then include:

  • Handling PreviewTextInput and blocking undesirable text
  • Handling PreviewKeyDown and blocking undesirable keystrokes
  • Handling paste operations and blocking undesirable text

#944 – Entering Special Characters into a TextBox

There are sometimes special characters that don’t exist on your keyboard, but that you want to enter into a text-based control (e.g. a TextBox).  To enter these characters:

  • Bring up the Character Map utility (press Windows key and enter “Character Map”)
  • Find that character that you want to insert
  • If the character has a “Keystroke” sequence shown in the lower right corner of the window, you can enter it as follows:
    • Enable Num Lock
    • Hold down Alt key while entering all 4 digits shown, on the numeric keypad

For example, the Character Map utility shows “Alt+0169” as the keystroke combination for a copyright symbol.

944-001

If you hold down the Alt key and type “0169” on the numeric keypad, while a TextBox control has keyboard focus, the copyright symbol will be inserted.

944-002

If keystroke is not shown, you can press Select and then Copy and then paste into your text control.