#635 – Using a Value Converter to Change User Input

Instead of modifying user input by handling the TextChanged event, you can use a value converter to change the text input.  Below, we bind the Text property of a TextBox to a string property and specify a converter, which will convert vowels to uppercase.

<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication9"
        Title="TextChanged"
        Height="150" Width="400">

    <Window.Resources>
        <ResourceDictionary>
            <local:CapVowelsConverter x:Key="capVowelsConverter"/>
        </ResourceDictionary>
    </Window.Resources>

    <StackPanel Orientation="Vertical">
        <TextBox HorizontalAlignment="Center" Width="150" Margin="10"
                 Text="{Binding Path=MyText, Converter={StaticResource capVowelsConverter}, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Content="What Is My Text?" HorizontalAlignment="Center" Margin="10" Click="Button_Click"/>
    </StackPanel>
</Window>

Here’s the code for the value converter:

    public class CapVowelsConverter : IValueConverter
    {
        // From bound property TO the control -- no conversion
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }

        // To bound property FROM the control -- capitalize vowels
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string input = (string)value;

            const string vowels = "aeiou";

            StringBuilder sbInput = new StringBuilder(input);
            for (int i = 0; i < sbInput.Length; i++)
            {
                if (vowels.Contains(char.ToLowerInvariant(sbInput[i])))
                    sbInput[i] = char.ToUpper(sbInput[i]);
            }

            return sbInput.ToString();
        }
    }


Advertisement

#634 – Modifying Text in the TextChanged Event

Text-based controls like TextBox fire the TextChanged to indicate that their text has changed.  You can use this event to make changes to text being entered by the user, for example to convert all vowels in the TextBox to their uppercase equivalents.  This is possible because you can just set the Text property of a TextBox control from within the event.

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            Trace.WriteLine(string.Format("=>TextBox_TextChanged, now {0}", ((TextBox)sender).Text));
            TextBox tb = (TextBox)sender;

            // Preserve caret position so that we can later restore it
            int pos = tb.CaretIndex;

            tb.Text = CapVowels(tb.Text);

            tb.CaretIndex = pos;
        }

        private string CapVowels(string input)
        {
            const string vowels = "aeiou";

            StringBuilder sbInput = new StringBuilder(input);
            for (int i = 0; i < sbInput.Length; i++)
            {
                if (vowels.Contains(char.ToLowerInvariant(sbInput[i])))
                    sbInput[i] = char.ToUpper(sbInput[i]);
            }

            return sbInput.ToString();
        }

#633 – TextChanged Event Fires After TextBox Text Has Changed

You can intercept the PreviewKeyDown event for a TextBox to look at each key pressed while the TextBox has focus.  You can also intercept the PreviewTextInput event to look at text that is being entered into the TextBox.  However, these events still won’t handle all possible changes to the text in the TextBox.  For example, you might right-click in the TextBox and select Paste to paste some text.

To see all changes to the text in a TextBox, you can handle the TextChanged event.  This event fires after the text has changed.

In the TextChanged event, the easiest way to inspect the text being entered is to just look at the value of the Text property.  This will contain the new contents of the TextBox.

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            Trace.WriteLine(string.Format("TextBox_TextChanged, Text now = [{0}]", ((TextBox)sender).Text));
        }

For example, if I just enter the text “Harpo”: