Introduction
I created a DecimalTextBox UserControl that stores some decimal check that I need to do, so I donβt need to recreate the check every time, and I can just use UserControl . This check has properties that you need to bind to, and so I created DependencyProperties , so I can bind to them, according to this article by Josh Smith .
PROBLEM
The verification check behaves strangely. When I enter an erroneous value in a TextBox , it displays as an error. However, when I try to change the value back in the code, the value displayed in the text box remains unchanged.
Here are the steps I follow that cause this error (in this example, 1 is an invalid value):
- Download the form and the default value is 0 .
- Enter 1 in the text box (and the text box goes red due to the result of the check and error)
- In the code, I set the property associated with the text box to 0
- The form is still displayed 1 in the red text box
CODE EXAMPLE
I prepared an example demonstrating a problem that can be downloaded here.
I will write part of the code here if you want to tell me more.
ValidationTestControl XAML
<UserControl x:Class="WPFTestProject.ValidationTestControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:v="clr-namespace:WPFTestProject" x:Name="ValidationTest" Height="50" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBlock Text="Type 'Banana' here: "></TextBlock> <TextBox MinWidth="100"> <TextBox.Text> <Binding ElementName="ValidationTest" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" ValidatesOnDataErrors="True" ValidatesOnExceptions="True"> <Binding.ValidationRules> <v:NotBananaValidationRule> <v:NotBananaValidationRule.NotWhatBinding> <v:NotBananaBinding x:Name="NotBananaValidationBinding"></v:NotBananaBinding> </v:NotBananaValidationRule.NotWhatBinding> </v:NotBananaValidationRule> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> <TextBlock Text=" (the text will give error when = 'Banana')"></TextBlock> </StackPanel> </Grid>
ValidationTestControls Code Behind
(yes, I do not know very MVVM, but I felt that it was normal for this autonomous control)
public partial class ValidationTestControl : UserControl { public ValidationTestControl() { InitializeComponent(); Banana = "Banana"; Binding BananaBinding = new Binding("Banana"); BananaBinding.Source = this; NotBananaValidationBinding.SetBinding(NotBananaBinding.NotWhatProperty, BananaBinding); } public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(ValidationTestControl), new PropertyMetadata()); public static DependencyProperty BananaProperty = DependencyProperty.Register("Banana", typeof(string), typeof(ValidationTestControl), new PropertyMetadata()); public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public string Banana { get { return (string)GetValue(BananaProperty); } set { SetValue(BananaProperty, value); } } }
ValidationRule and FrameWorkElement are for binding
public class NotBananaValidationRule:ValidationRule { private NotBananaBinding _notWhatBinding; public NotBananaBinding NotWhatBinding { get { return _notWhatBinding; } set { _notWhatBinding = value; } } public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { string what = value.ToString(); if(what == _notWhatBinding.NotWhat||string.IsNullOrEmpty(what)) return new ValidationResult(false, "Please enter a string that is not " + _notWhatBinding.NotWhat); else return new ValidationResult(true, null); } } public class NotBananaBinding : FrameworkElement { public static readonly DependencyProperty NotWhatProperty = DependencyProperty.Register( "NotWhat", typeof(string), typeof(NotBananaBinding), new UIPropertyMetadata()); public string NotWhat { get { return (string)GetValue(NotWhatProperty); } set { SetValue(NotWhatProperty, value); } } public NotBananaBinding() { } }
Basically what this code does, check to see if you typed βBananaβ and then returned a validation error. The control provides dependency properties because I want to be able to bind to them when using the control. FrameworkElement NotBananaBinding allows me to create dependency properties (because it is a DependencyObject , so I can bind the material for validation. ValidationRule has a NotBananaBinding property that saves the dependency property and uses it in the validation method.
I know my property names are a little crappy, sorry. The fact is that in this example, a good job is to display the error. In my haste to give an example, I did not name the variables very well. If you find crappy code , download the sample here.
WHAT I PICTURE SOON
Basically this problem is apparently caused by the fact that I actually do not change the value.
Even if I call OnPropertyChanged in the property because the value is not different, it does not try and does not overestimate the check.
I can obviously change the value to some arbitrary Valid value and then change it to the one I want and it will work, but I was hoping there was a way to get the validation manually, re-evaluate the value and then change it and etc. Changing it back and forth will be messy.
Conclusion
I'm doing something wrong (maybe something about how I applied validation and binding to Josh Smith's post)
Is this just a C # error, or is this behavior? If so, why?
Are there any elegant ways to fix this?
u_u