Strong Validation in WPF TextBoxes
When working with data-bound applications in Windows Presentation Foundation (WPF), validation is crucial to ensure that user inputs are both valid and safe. One common scenario involves a TextBox
bound to a nullable decimal property, such as height. However, a problem arises when the TextBox
can still lose focus even when an invalid value is entered. In this blog post, we will explore effective strategies to implement strong validation in WPF, specifically focusing on two key methods to handle the input state of a TextBox
.
The Problem: Ensuring Valid User Input
Consider a TextBox
in your application bound to a decimal property, which allows users to input height values. When a user enters a value that cannot be converted to a decimal, the TextBox
highlights an error. However, there is a risk that the user may move focus away from the TextBox
, leaving the application in an invalid state. To address this, we will look at two potential solutions:
- Prevent the
TextBox
from losing focus until it has a valid value. - Revert the
TextBox
content to the last valid value when it loses focus with an invalid input.
Solution 1: Preventing Focus Loss
One effective way to keep the focus on the TextBox
until valid input is provided is to handle the PreviewLostKeyboardFocus
event. This approach entails blocking the focus shift programmatically any time an invalid state is detected. Here’s how you can implement this solution:
XAML Implementation
First, add an event handler for PreviewLostKeyboardFocus
in your TextBox
definition:
<TextBox PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus"
Text="{Binding Height, UpdateSourceTrigger=PropertyChanged,
ValidatesOnExceptions=True,
Converter={StaticResource NullConverter}}" />
C# Code Implementation
Next, implement the event handler in your code-behind to prevent focus loss:
private void TextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
TextBox box = sender as TextBox;
var binding = box.GetBindingExpression(TextBox.TextProperty);
// Check for validation errors
if (binding.HasError) {
// Block focus shift
e.Handled = true;
}
}
By using this method, the TextBox
will not allow focus loss until the user has entered a valid decimal. This ensures data integrity at the input stage.
Solution 2: Reverting to Last Valid Value
Another solution is to revert the TextBox
content to the last valid entry when the focus is lost. This can be particularly useful in user-friendly applications where retaining the last valid state is preferred.
Existing Method
You might already have implemented a basic form of this in your LostKeyboardFocus
event handler. For completeness, here is how it can be structured:
private void TextBox_LostKeyboardFocus(object sender, RoutedEventArgs e) {
TextBox box = sender as TextBox;
var binding = box.GetBindingExpression(TextBox.TextProperty);
if (binding.HasError) {
binding.UpdateTarget(); // Reverts to last valid value
}
}
While this method works, it might not provide the most elegant solution in scenarios where immediate feedback is warranted. Additionally, if users continue to make invalid inputs, it can lead to frustration if they are confused about previous values they were trying to enter.
Conclusion
Implementing strong validation in WPF TextBox
controls can significantly enhance user experience by ensuring that only valid data is processed. By either preventing focus loss or reverting to the last valid value, you can maintain the integrity of the data your application collects. Choose the method that best suits your application needs to provide an efficient and user-friendly experience.
By employing these techniques, you can enhance the robustness of your data entry forms and lead your users towards successful interactions with your application.