WPF Textbox Binding not Responding when ValidationRule Fired - wpf

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.

Related

Validation is not getting fired when setting updatesourcetrigger to lost focus

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.:)

WPF: Initializing a TextBox and binding it to a validation rule

I try to validate the IP-Address a user enters into a text box of a WPF Dialog. The text box is supposed to be initialized with 127.0.0.1. This is the XAML:
<TextBox
Height="23"
Width="98"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Name="ip_address"
Text="127.0.0.1">
<TextBox.Text>
<Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:IPValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
This attempt to bind the text box to the validation rule causes an error, because the attribute Text already has the value 127.0.0.1. My question is this: How can I achieve initializing and binding simultaneously?
Regards, RSel
PS: Initializing the text box in Window_Loaded doesn't work either. The box just remains empty. Without the binding to the rule it works.
A couple options:
Set an initial value in the property that the textbox is bound to. The binding should pick this up when the control loads. I'm not sure if this meets your goals though.
Use the TargetNullValue property of the binding object to specify what to show when the source is null.
Here's MSDN on option 2:
http://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.targetnullvalue.aspx

WPF/XAML: ExceptionValidationRule different when applying in code vs markup?

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());
}
}

WPF TexBox TwoWay Binding Problem when ValidationRules used

I seem to have a problem with TwoWay DataBinding - my application has a window with a bunch of textboxes that allow to edit values of the properties they are bound to. Everything works well except for textboxes that also have a validation rule defined, in which case no text is displayed in the textbox when the window opens (binding back-to-source still works fine for those). If I remove Validation rule, everything's back to normal. I searched for an answer to this for a few hours now, but somehow did not even find anyone else complaining of the same issue. I am completely new to WPF, and I am sure it is just a silly mistake I have somewhere in my code... I will greatly appreciate any feedback...
<TextBox Margin="40,2,20,0" Grid.Column="0" Grid.Row="1" Background="#99FFFFFF" >
<Binding Path="LastName" Mode="TwoWay" ValidatesOnDataErrors="true" UpdateSourceTrigger="LostFocus" >
<Binding.ValidationRules>
<validation:StringNameValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox>
It would be nice to know what your binding source is, does it implement INotifyPropertyChanged for example?
Without nothing that, the only thing I can think of is the NotifyOnValidationError property on the binding class. Try setting it to true.

Can you use ValidationRules on ListBox.SelectedItems?

I want to use ValidationRules to verify that a few ListBox controls have at least one item selected.
I tried doing it this way:
<ListBox ItemsSource="{Binding Path=AvailableItems}"
Behaviors:MultiSelectorBehaviours.SynchronizedSelectedItems="{Binding ChosenItems}"
x:Name="ListBoxItems">
<ListBox.Tag>
<Binding ElementName="ListBoxItems" Path="SelectedItem">
<Binding.ValidationRules>
<ValidationRules:NotNullValidationRule />
</Binding.ValidationRules>
</Binding>
</ListBox.Tag>
</ListBox>
But my NotNullValidationRule never gets called. Note that the SynchronizedSelectedItems is a special attached property I use to synchronize the SelectedItems to a custom collection (described here). That's why I do my validation on a 'fake' Binding applied to Tag instead.
Is there a way to validate ListBox.SelectedItems?
Validation is done only in TwoWay and OneWayToSource mode bindings. If you turn the Binding around, binding SelectedItem to tag in either TwoWay or OneWayToSource mode the validation is triggered.
Validation is there to protect the target property. So when you set Tag, validation makes sure the Tag is valid and SelectedItem can be set with a new value. The following code works (SelectedItem binds TwoWay automatically IIRC.)
<ListBox x:Name="list">
<ListBox.SelectedItem>
<Binding ElementName="list" Path="Tag">
<Binding.ValidationRules>
<local:SelectedValidationRule />
</Binding.ValidationRules>
</Binding>
</ListBox.SelectedItem>
</ListBox>

Resources