0
votes

I want to allow the user to input only text that is validated by the TextBox binding validation rules. I figured out a way of doing that:

public static void PreviewTextChanged(
    object sender,
    PreviewTextChangedEventArgs e)
{
    var textBox = e.Source as TextBox;
    var bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty);
    if (!ReferenceEquals(null, bindingExpression))
    {
        // save original parameters for possible restoration
        var originalSelectionStart = textBox.SelectionStart;
        var originalSelectionLength = textBox.SelectionLength;
        var originalText = textBox.Text;

        // check validation
        textBox.Text = e.Text;
        if (!bindingExpression.ValidateWithoutUpdate())
        {
            // restore original values
            textBox.Text = originalText;
            bindingExpression.UpdateSource();
            textBox.SelectionStart = originalSelectionStart;
            textBox.SelectionLength = originalSelectionLength;
        }
        else
        {
            // correct the selection
            var selectionStart = originalSelectionStart +
                originalSelectionLength +
                e.Text.Length -
                originalText.Length;
            textBox.SelectionStart = Math.Max(selectionStart, 0);
            textBox.SelectionLength = 0;
        }

        e.Handled = true;
    }
}

The code above works. But it would be much simpler, and less bug-prone, if I could find a way to check if the new value is valid without updating the binding target. Is there one?

1

1 Answers

0
votes

I think it's easier in this case to relay on Binding Converters. The converter will be called every time the data should be assigned to the binded field. Inside methods of it, you can validate the input of the data and based on validation result return or old data (cause validation fails) recovered from ModelView or accept it, in case when validation succeeded.

Hope this helps.