wpf validation rules problem with textbox - wpf

I created a class IntegersValidationRule which inherits from ValidationRule. Now I don't know what code should I write in XAML. That's what I have:
<TextBox Name="defaultTxt"
Height="23" Width="200">
<TextBox.Text>
<Binding UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<what:IntegersValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
I know that either I'm so stupid that I can't understand in many tutorials what Path in Binding property means, why should we use Binding here when there's no binding required and what should I use instead of 'what' word inside Binding.ValidationRule.

what is an xmlns (see MSDN) which needs to point to the namespace in which your validation rule class is declared, e.g.
xmlns:what="clr-namespace:MyApp.MyValidationRules"
If you add no Path (- how about reading this if you do not understand it? -) the binding will bind to the current DataContext, whatever that may be in your case.

Question 1: validators work on bindings. That is why you specify the rule on a binding. As soon as then value will be updated to the source (object that the control binds to) the rule is checked.
Question 2: See H.B. 's answer

Related

DesignTime Error Wpf ValidatesOnTargetUpdated NullReferenceException

I have the same question as in the link below, but the answers where not satisfying for me.
ValidationRule ValidatesOnTargetUpdated NullReferenceException at Design Time
XAML
<TextBox x:Name="MyTextBox">
<TextBox.Text>
<Binding Path="MyText">
</Binding>
</TextBox.Text>
</TextBox>
Code-Behind
Binding binding = BindingOperations.GetBinding(MyTextBox, TextBox.TextProperty);
binding?.ValidationRules.Add(new MyValidationRule()
{
ValidatesOnTargetUpdated = true
});
It works with this section in code behind. But I am looking for a only XAML solution, because it is more intuitive and for me better maintainable. Does anybody have an idea?
I found a "solution" (or more a workaround) on my own. The designer works for me if I change ValidatesOnTargetUpdated to ValidationStep with the wished value.
Attention: For example, the TextBox behaves differently if you put in ValidationStep="UpdatedValue" and ValidationStep="ConvertedProposedValue". More information on ValidationRule with ValidationStep="UpdatedValue" is called with BindingExpression instead of updated value.
However, I could not find why ValidatesOnTargetUpdated did not work.

I need an attached property to monitor parent for INotifyDataErrrorInfo

If I have the following binding
<TextBox Text="{Binding XXX.Name, ValidatesOnNotifyDataErrors=True}"/>
it doesn't work because only the DataContext implements INotifyDataErrorInfo and raises "XXX.Name" errors but ValidatesOnNotifyDataErrors tries to monitor XXX for error events not the data context.
However I am sure somebody could figure out how to write an attached property to do the following
<TextBox Grid.Column="5" Text="{Binding Binding.Name, c:ValidatesOnNotifyDataErrorsOnDataContext=True}"/>
where the data context is monitored not the child. Anybody got an idea how to start with that?
I think this is possible to implement, but because of the flexibility of bindings (RelativeSource, MultiBindings and whatnot) it would be difficult to make something like this that is truly robust. Personally, I think it would be cleaner to to implement INotifyDataErrorInfo at every level of the structure (and for parts of the structure that you don't own, like your Point example, use proxy classes that mirror the properties).
Anyway, Binding is a MarkupExtension, not a DependencyObject, which means attached properties can't be applied to it. You could inherit Binding to add your own properties, but this isn't very useful since it doesn't give you any overridable methods.
It shouldn't be necessary to extend Binding though, since all you want is a custom ValidationRule. Setting ValidatesOnNotifyDataErrors=True is equivalent to adding a NotifyDataErrorValidationRule:
<TextBox>
<TextBox.Text>
<Binding Path="XXX.Name">
<Binding.ValidationRules>
<NotifyDataErrorValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox>
</TextBox>
So you just need to replace NotifyDataErrorValidationRule with your own rule. If you override this Validate overload (which is passed the binding expression), you should be able to access the full binding path (through ParentBinding) and look up an error.

Add ValidationRules into a single xaml line OR shorthand ValidationRules

I'm using a PasswordBox which exposes a dependency property such that I can bind to it. The problem is that by using it like so, I cannot shorthand the Binding.ValidationRules to this syntax:
<PasswordBox services:RPLPasswordBoxBinder.BindPassword="True"
services:RPLPasswordBoxBinder.BoundPassword="{Binding Path=LoginUser.Parola, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</PasswordBox>
I set my ValidationRules to a textbox like this:
<TextBox.Text>
<Binding Path="LoginUser.Parola" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<some validation rule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
Is there any way to specify the ValidationRules collection to my PasswordBox in a single xaml line? Or maybe there's another clever solution for validating user input into my password box?
Some clarifications:
I'm using MVVM and I don't want to use code behind.
I want to add only a single ValidationRule. Maybe the problem with shorthanding Binding.ValidationRules is that this property is a collection. One validationrule would suffice in my situation.
There's a similar question on stackoverflow here. My problem is different as I don't just want to increase readability but actually validate my PasswordBox.
I suggest that you base your data model class on IDataErrorInfo and then validation is performed there and not in the code behind.
There are plenty of examples, but here's one for starters and another here.

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.

Programmatically change validation rule in WPF TextBox

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.

Resources