Combining ValidationRule and Value Converters for a textbox
I have a simple problem that I just cant find a good solution for. I have a textbox bound to a double property value. The user can enter values into the textbox, but I only want to allow values between 0 and 100. I would like to show a red box around the textbox if an invalid value is entered while the textbox still has focus (UpdateSourceTrigger="PropertyChanged"). Should the user click away from the textbox, I want to clamp the value using a value converter on UpdateSourceTrigger="LostFocus".
Its easy to do either the validation rule or the converter, but I can not combine them as I want the validation to trigger on UpdateSourceTrigger="PropertyChanged" and the converter should trigger on UpdateSourceTrigger="LostFocus". Unfortunately I can only choose either one or the other when setting up the binding on my TextBox.Text.
Any good ideas about how I could implement this f开发者_StackOverflow中文版unctionality?
Thank you
/Peter
That's an interesting question. I'm not sure I have a complete solution, but I'd like to throw out a couple ideas.
What do you think of creating a new class that derives from TextBox? It could have two dependency properties, MinValue and MaxValue. Then it could override OnLostFocus. (Disclaimer: I haven't tested the following code.)
public class NumericTextBox : TextBox
{
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(double), typeof(NumericTextBox), new UIPropertyMetadata(Double.MinValue));
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double), typeof(NumericTextBox), new UIPropertyMetadata(Double.MaxValue));
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetValue(MinValueProperty, value); }
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}
protected override void OnLostFocus(System.Windows.RoutedEventArgs e)
{
base.OnLostFocus(e);
double value = 0;
// Parse text.
if (Double.TryParse(this.Text, out value))
{
// Make sure the value is within the acceptable range.
value = Math.Max(value, this.MinValue);
value = Math.Min(value, this.MaxValue);
}
// Set the text.
this.Text = value.ToString();
}
}
This would eliminate the need for a converter, and your binding can use UpdateSourceTrigger=PropertyChanged to support your validation rule.
My suggestion admittedly has its drawbacks.
- This approach would require you to have validation-related code in two places, and they'd need to match. (Maybe you could override OnTextChanged too, and set the red border there instead.)
- This approach requires you to put rules in the view layer rather than in business objects, which you may or may not find acceptable.
精彩评论