Can you replace characters in a textbox as you type? Can you replace characters in a textbox as you type? wpf wpf

Can you replace characters in a textbox as you type?


The best way to accomplish this is using the TextChanged event:

    private void OnTextChanged(object sender, TextChangedEventArgs e)    {        var tb = (TextBox)sender;        using (tb.DeclareChangeBlock())        {            foreach (var c in e.Changes)            {                if (c.AddedLength == 0) continue;                tb.Select(c.Offset, c.AddedLength);                if (tb.SelectedText.Contains(' '))                {                    tb.SelectedText = tb.SelectedText.Replace(' ', '_');                }                tb.Select(c.Offset + c.AddedLength, 0);            }        }    }

This has several advantages:

  • You don't go through the entire string every time, just the replaced part
  • It behaves well with the undo manager and with pasting text
  • You can easily encapsulate it into an attached property which can be applied to any text box


You can use an IValueConverter. It involves quite a bit of code, but it's the preferred way if you ever want to go the MVVM path, or just do things the WPF way.

First, create a class that implements IValueConverter

public class IllegalCharactersToUnderscoreConverter    : IValueConverter{    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        var stringValue = value as String;        if(stringValue == null)            return value;        return RemoveIllegalCharacters(stringValue);    }    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        return value;    }}

Import the namespace containing your ValueConverter

<Window x:Class="WpfApplication1.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:local="clr-namespace:WpfApplication1"        Title="MainWindow" Height="350" Width="525">

Create an instance of your converter in Window.Resources

<Window.Resources>    <local:IllegalCharactersToUnderscoreConverter x:Key="IllegalCharactersToUnderscore" /></Window.Resources>

Use the converter in your binding expression. UpdateSourceTrigger=PropertyChanged is required for the text to be converted as you type.

<TextBox Text="{Binding MyText,                 Converter={StaticResource IllegalCharactersToUnderscore},                 UpdateSourceTrigger=PropertyChanged}"/>


You could subclass TextBox you can just override the Metadata of the TextBox Text property

public class FilteredTextBox : TextBox{    public FilteredTextBox()    {        TextBox.TextProperty.OverrideMetadata(typeof(FilteredTextBox), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null, CoerceMyTextValue, true, UpdateSourceTrigger.PropertyChanged));    }    private static object CoerceMyTextValue(DependencyObject d, object baseValue)    {        if (baseValue != null)        {            var userEnteredString = baseValue.ToString();            return userEnteredString.Replace(' ', '_');        }        return baseValue;    }}

And you dont need to use bindings at all, this will just update the internal TextBox TextProperty as you type

<Window x:Class="WpfApplication13.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        Title="MainWindow" Height="428" Width="738" Name="UI"         xmlns:my="clr-namespace:WpfApplication13" >    <StackPanel>        <my:FilteredTextBox />    </StackPanel></Window>