Click here to Skip to main content
15,887,585 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have a validation problem on a WPF window.

I have a TextBox, bound to a simple string property in the view-model. I want to ensure the box can never be empty. The TextBox is declared as follows:

<TextBox x:Name="TextBoxName" Validation.Error="TextBox_Error" >
    <TextBox.Text>
        <Binding Path="CustomerName" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <u:NonZeroLengthStringValidator/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>


As you can see, I have set it to update the source on ever character-change, attached an event handler for validation errors, and created my own validator that tests for an empty string.

If there is a single character 'a' in the TextBox and I delete it, the validation rule returns an error and the event fires. In the event, I pop up a warning dialog, telling the user that the field cannot be empty. What I then want to do is leave the last character 'a' in the box, so the screen as a whole does not need to worry about being in an invalid state (which would hugely increase the complexity of handling the other fields and controls on the screen).

How can I do this?

What I have tried:

I have tried many options, but my real sticking point is that the set on CustomerName is not called when the validation rule fails. This leaves the backing field containing the single character 'a' while the UI shows an empty box. If I force OnPropertyChanged("CustomerName") to update the UI, the validation process runs again and I get a second dialog box.

So, in summary, I almost have it working but I either get the UI out-of-step with the backing field or I get two error dialogs.

Can anyone think of a way round this?
Posted
Updated 31-May-17 3:06am

1 solution

I personally use an event trigger on the event lost focus to do a string.empty check. If the string is empty then I replace it with my default string. I also use the command property to fire the validation in the view model, or you can extend a behavior in the textbox control to do this as well.

The event trigger is found in the System.Windows.Interactivity .dll so it is something like:
HTML
xmlns:i=clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity


Then,

<TextBox x:Name="TextBoxName" Validation.Error="TextBox_Error" >
    <TextBox.Text>
        <Binding Path="CustomerName" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <u:NonZeroLengthStringValidator/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="LostFocus">
             <i:InvokeCommandAction Command={Binding ElementName=TextBoxName, Path=Datacontext.YourCommandPropertyHere/>
         </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>



The other solution would be to extend Textbox with a behavior using the same .dll
A good example of how it works can be found here, Custom Behaviors
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900