I am using below code to validate textbox.
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<Validate:RquiredFiledValidation ErrorMessage="Please Provide Login Name"></Validate:RquiredFiledValidation>
</Binding.ValidationRules>
</Binding>
Above code is working fine but when changing updatesourcetrigger to Lostfocus it stop working.
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="LostFocus" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<Validate:RquiredFiledValidation ErrorMessage="Please Provide Login Name"></Validate:RquiredFiledValidation>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
Any help would be appreciated.
The spelling of Field is wrong:
<Validate:RquiredFieldValidation ErrorMessage="Please Provide Login Name"></Validate:RquiredFieldValidation>
UPDATE:
From the UpdateSourceTrigger Enumeration page on MSDN:
PropertyChanged: Updates the binding source immediately whenever the binding target property changes, which means that the source value will be updated each time the bound property changes.
whereas
LostFocus: Updates the binding source whenever the binding target element loses focus i.e., the source value will be updated each time the destination control loses focus. If you don’t make any property change on target, source will stay the same.
As Jim Zhou says here, we could invoke the BindingExpression.UpdateSource method to force the data source to reset. So in this case, we can hook up LostFocus event on the TextBox and invoke the
BindingExpression.UpdateSource method explicitly. Something like this:
private void OnLostFocus(object sender, RoutedEventArgs e)
{
TextBox text = sender as TextBox;
BindingOperations.GetBindingExpression(text, TextBox.TextProperty).UpdateSource();
}
Also have a look at ValidatesOnTargetUpdated property of ValidationRule. It will validate when the data is first loaded. This is good if you're trying to catch empty or null fields. Than you can add something like this in your Binding Validation rule:
<DataErrorValidationRule ValidatesOnTargetUpdated="True" />
Not much related but you may like dkozl's answer.
Hope that helps.:)
Related
In wpf controls, such as TextBox, you can set ValidatesOnDataErrors=true.
You can also want to change the default value for UpdateSourceTrigger.
For insert operations the textbox initial value is often empty, so its content is supposed to be not valid and it will be rendered with a red border (sure you can override this with styles and templates and obtain what you want). My desired behavior is to validate the content of a control only after the user has changed its content or when he tries to save the data.
It seems to me that the only way to achieve this is to set UpdateSourceTrigger=Explicit, which is not very friendly with pure MVVM.
I have already read the following article, but I'm looking for something simpler.
http://www.shujaat.net/2011/01/updatesourcetrigger-explicit-for-mvvm.html
Thanks
Filippo
Set DataErrorValidationRule like this:
<TextBox>
<TextBox.Text>
<Binding Path="PropertyName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<DataErrorValidationRule ValidatesOnTargetUpdated="False"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
I have a ValidationRule on a Text Box. When the ValidationResult returns true, this fires the set on the property that the text box is bound to.
When the ValidationResult returns false, the set is not fired.
Any pointers as to why its not firing, and how to solve it, greatly appreciated.
Thanks
Joe
Here is the XAML of the Text Box :
<Binding Path="CorrectEntry" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True" >
<Binding.ValidationRules>
<localValidation:CorrectEntryValidationRule x:Name="validator" ValidatesOnTargetUpdated="True"> <localValidation:CorrectEntryValidationRule.RangeContainer>
<localValidation:CorrectEntryRangeContainer
DataContext="{Binding
Source={StaticResource DataContextBridge},
Path=DataContext}"
Min="{Binding Lower}"
Max="{Binding Upper}"
/>
</localValidation:CorrectEntryValidationRule.RangeContainer>
</localValidation:CorrectEntryValidationRule>
</Binding.ValidationRules>
</Binding>
See the documentation for Validation Rule. it is by design that the property don't get set when Validation Rule returns false.
You should not use Validation Rule, if you want your Propery to be set. You should inherit your class from IDataErrorInfo. And implement the 2 methods from that interface.
This is the normal and usually wanted behavior, if your data is invalid you don't want it to be saved in your model.
(If you want to do validation via exceptions thrown in the setter you can use a property on the binding)
I've run across the need to apply the ExceptionValidationRule to many textboxes on a form in WPF. I can do this with markup and I get the desired result (the textbox gets a red outline when an invalid value is entered) but only when I supply the rule in markup:
<TextBox x:Name="Name" Width="150" >
<TextBox.Text>
<Binding Path="Name" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
But when I apply the value using code:
Name.GetBindingExpression(TextBox.TextProperty).ParentBinding.ValidationRules.Add(new ExceptionValidationRule());
I don't get the desired results. This code is applied in a userControl's constructor after the InitalizeComponent() call. The user control has the textbox "Name" as a child control.
I've gone through and I can see, when using both, that two validation rules are put in the ValidationRules collection but when I am using just the code version I don't get the desired result of a red outline around the textbox when an invalid value is entered.
Am I just misunderstanding a fundamental rule to WPF?
Or, is there a way I can apply this validation rule using a Style? I'd prefer that, to tell you the truth.
Thanks,
M
You can't change a Binding after it has been used, and apperently that goes for the ValidationRules as well. You can create a new Binding in code but that's probably not what you're after.
Binding binding = new Binding("Name");
binding.Mode = BindingMode.TwoWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
binding.NotifyOnValidationError = true;
binding.ValidationRules.Add(new ExceptionValidationRule());
nameTextBox.SetBinding(TextBox.TextProperty, binding);
A Style won't work either since a Binding or ValidationRule doesn't derive from FrameworkElement. What I would do in your situation is a subclassed Binding where you add all the things you need. Something like this
<TextBox x:Name="Name" Width="150" >
<TextBox.Text>
<local:ExBinding Path="Name"
Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"/>
</TextBox.Text>
</TextBox>
The ExBinding, adding ValidationRule etc.
public class ExBinding : Binding
{
public ExBinding()
: base()
{
NotifyOnValidationError = true;
ValidationRules.Add(new ExceptionValidationRule());
}
}
I have a textbox that has a ValidationRule applied to it:
<TextBox Style="{StaticResource StandardTextBox}"
Grid.Column="1" Grid.Row="4"
IsReadOnly="{Binding SaveModeText}"
MaxLength="50">
<TextBox.Text>
<Binding Path="Individual.SurName"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True"
ValidatesOnExceptions="True"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<valid:RequiredTextBoxValidationRule
ErrorMessage="Please enter a last name" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
When the page loads the textbox contains the correct value based on its binding. If I delete the value from the textbox the ValidationRule fires properly and I see the error message as expected. My application contains a "Discard Changes" button which reloads the DataContext. The hope was it would reset all of the bindings and once again this textbox would display the original value. For some reason, all other values on the page that do not have a ValidationRule associated with them get reset properly, but this textbox does not.
If I remove the ValidationRule from the XAML the value resets properly. If I handle validation through IDataErrorInfo, the validation fires properly and the value resets properly. Because I have used ValidationRules throughout my application, I was wondering if anyone had come across this issue and resolved it. At this point I would prefer to stick with the implemented ValidationRules if possible, instead of switching everything over to IDataErrorInfo.
Since your you are modifying the value in code, wouldn't you need to have Mode=TwoWay in your binding for it to update? I don't have time to dig in and see if that's what's wrong, but it may be a place to start.
I have a text input area defined like this:
<TextBox>
<TextBox.Text>
<Binding Path="MyProperty">
<Binding.ValidationRules>
<valid:MyValidator/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
My problem is that, depending on another setting, what is supposed to be inserted here varies. And thus, the validation behavior of the input data should change.
How can I in the code behind change the active validation rule for a certain textbox?
Use BindingOperations.GetBinding() to get the Binding object for the TextBox.Text. Then manipulate the binding's ValidationRules collection as you see fit.
Binding binding = BindingOperations.GetBinding(myTextBox, TextBox.TextProperty);
binding.ValidationRules.Clear();
binding.ValidationRules.Add(myCrazyValidationRule);
The most hacky solution that comes to mind is to define one textbox for each of the validation rules that should be able to be set. Bind one textbox to each of the validation rules. Then, depending on the external setting/condition, collapse/hide all the textboxes except the one with the validation rule that should be applied.