Joseph Sturtevant
Joseph Sturtevant

Reputation: 13360

Strong Validation in WPF

I have a databound TextBox in my application like so: (The type of Height is decimal?)

    <TextBox Text="{Binding Height, UpdateSourceTrigger=PropertyChanged, 
                            ValidatesOnExceptions=True, 
                            Converter={StaticResource NullConverter}}" />
    public class NullableConverter : IValueConverter {
        public object Convert(object o, Type type, object parameter, CultureInfo culture) {
            return o;
        }

        public object ConvertBack(object o, Type type, object parameter, CultureInfo culture) {
            if (o as string == null || (o as string).Trim() == string.Empty)
                return null;
            return o;
        }
    }

Configured this way, any non-empty strings which cannot be converted to decimal result in a validation error which will immediately highlight the textbox. However, the TextBox can still lose focus and remain in an invalid state. What I would like to do is either:

  1. Not allow the TextBox to lose focus until it contains a valid value.
  2. Revert the value in the TextBox to the last valid value.

What is the best way to do this?

Update:

I've found a way to do #2. I don't love it, but it works:

private void TextBox_LostKeyboardFocus(object sender, RoutedEventArgs e) {
    var box = sender as TextBox;
    var binding = box.GetBindingExpression(TextBox.TextProperty);
    if (binding.HasError)
        binding.UpdateTarget();
}

Does anyone know how to do this better? (Or do #1.)

Upvotes: 1

Views: 2740

Answers (2)

David Schmitt
David Schmitt

Reputation: 59346

You can force the keyboard focus to stay on the TextBox by handling the PreviewLostKeyBoardFocus event like this:

     <TextBox PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" /> 
     private void TextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
         e.Handled = true;
     }

Upvotes: 2

Dillie-O
Dillie-O

Reputation: 29725

It sounds to me that you'll want to handle two events:

GotFocus: Will trigger when the textbox gains focus. You can store the initial value of the box.

LostFocus: Will trigger when the textbox loses focus. At this point you can do your validation and decide if you want to roll back or not.

Upvotes: 0

Related Questions