Behavior of TextBox elements — Digitteck
Behavior of TextBox elements
dotnet·11 February 2018·2 min read

Behavior of TextBox elements

Description

When working with input data (TextBox) you will usually have a certain data type that you expect from the end user. This may be an integer or string type. Even if it's a string then you may want to check if it matches a certain pattern. You can of course use a validation and that will simply color in red the faulty lines but that was not what I was looking for — I needed something that will not allow the user to insert a string in a number field.

There is a nice library (Interactivity) where you can define behaviours, but I was creating an add-in and this proved to be a problem, so I decided to make something simple but pretty powerful. Of course you may extend it as you like:

Solution

csharp
public class TextboxStrict
{
    private Regex validate;
    private string lastKnowText = "";
    private string defaultText = "";
    private int defaultCaretIndex = 0;
    private int lastKnownCaretIndex = 0;

    /// inputChange - marks that the change was made by this class so that
    /// when text changed is fired again - caret index will not move its position
    private bool inputChange = false;

    public TextboxStrict(string regexPattern, string startWith = "")
    {
        validate = new Regex(regexPattern);
        ///lastKnownText will be the placeholder of any good changes in text status
        this.lastKnowText = startWith;
        ///default text will be the holder of the default text on initialize and on text == ""
        this.defaultText = startWith;

        this.lastKnownCaretIndex = startWith.Length;
        this.defaultCaretIndex = startWith.Length;
    }

    public void AttachTo(TextBox textBox)
    {
        ///Initializing text box data with default entries
        textBox.Text = this.defaultText;
        textBox.CaretIndex = this.defaultCaretIndex;

        textBox.TextChanged += EvtTextChanged;
        textBox.SelectionChanged += EvtSelectionChanged;
    }

    /// <summary>
    /// Validate function
    /// </summary>
    private bool Validate(string text)
    {
        return validate.IsMatch(text);
    }

    /// <summary>
    /// Making sure last known caret index keeps track
    /// </summary>
    private void EvtSelectionChanged(object sender, RoutedEventArgs e)
    {
        TextBox textBox = (TextBox)sender;
        lastKnownCaretIndex = textBox.CaretIndex;
    }

    /// <summary>
    /// Validates text and keeps last known good one. Keeps track of caret index also
    /// </summary>
    private void EvtTextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textbox = (TextBox)sender;

        if (textbox.Text == "")
        {
            inputChange = true;
            textbox.Text = this.defaultText;
            textbox.CaretIndex = this.defaultCaretIndex;
        }
        ///If it doesn't validate - change back. Mark as internal change to not override the last index
        else if (!this.Validate(textbox.Text))
        {
            inputChange = true;
            textbox.Text = lastKnowText;
            textbox.CaretIndex = lastKnownCaretIndex;
        }
        else
        {
            if (!inputChange)
            {
                lastKnowText = textbox.Text;
                lastKnownCaretIndex = textbox.CaretIndex;
            }
            inputChange = false;
        }
    }
}

Usage

The class above will attach 2 events to the textbox (TextChanged and SelectionChanged).

csharp
public partial class MainWindow : Window
{
    TextboxStrict inputLimit = new TextboxStrict("^[0-9]{1,10}
quot;
, "0"); public MainWindow() { InitializeComponent(); inputLimit.AttachTo(TestTextBox); } }

Tags

WPFC#.NET
digitteck

© 2026 Digitteck