I am creating a WPF application that will use IDataErrorInfo
data validation, which my business objects implement. I have been working with this demo from a blog post to understand ValidatesOnDataErrors
.
The demo is a trivial app that binds a couple of text boxes to a Contact object and implements IDataErrorInfo
validation, using ValidatesOnDataErrors=True
in the data binding. To be valid, a text box has to have at least five characters.
Here is my problem: in the demo, validation is triggered whenever a text box loses focus. In fact, the text boxes initialize to an invalid state (red borders) when the application launches. My app has to put off validation until the user clicks the OK button to submit the page. At that time, the text boxes should be validated and put into an error state if invalid.
So, how would I defer validation on the text boxes until the user clicks the OK button? Thanks for your help.
Data binding has an UpdateSourceTrigger property. As the name implies, it specifies when to update the source of the binding. For the Text property, this is set to LostFocus by default. You could set this to Explicit and call the UpdateSource method of the BindingExpression in code. On the other hand, you could also defer the raising of the PropertyChanged event. However, these will not solve the problem of validation at application launch, I think. Hope this helps somehow.
Thanks to Michael for his help. Unfortunately, I need bindings to remain constantly synchronized, with only validation deferred. Otherwise, Michael's solution would do the job. So, I went in a slightly different direction. Here is the solution I ultimately implemented.
Simple demo: Let's start with the simplest case: My business objects implement
IDataErrorInfo
; let's assume I can modify how it is implemented. I give each business object an additional boolean property,ValidationEnabled
, and I modify theIDataErrorInfo
implementation to always return a null result if that property is false.The demo I mentioned in my original post uses a Contact object with two properties; FirstName and LastName. I added a ValidationEnabled property and modified the
IDataErrorInfo
implementation looks like this:In my version of the simple demo, I connect the Submit button to an event handler in code-behind that enables validation and refreshes the bindings for both text boxes:
Now the red outlines don't appear until I try to submit the form.
Real world: In my production app, I don't control the business objects, and I can't modify them as I did in my simple demo. So, I create a simple pass-through wrapper for the business object that exposes the properties to be databound to the view and links those properties to the corresponding properties of the wrapped business object. The wrapper implements IDataErrorInfo and contains the
ValidationEnabled
property.The wrapper's IDataErrorInfo implementation always returns null if validation is not enabled. If validation is enabled, then the wrapper calls the IDataErrorInfo implementation on the wrapped object and returns what it gets from there.
This approach will be familiar to anyone who uses the Model-View-ViewModel pattern. What we are doing is creating a view-model wrapper for a business object, which is considered an MVVM best practice by many developers. It separates the UI concern (supressing red borders until the page is submitted) from the business model concern (simple object validation).
Also, my production app will not use event handlers in code-behind. Per MVVM, the button will be wired to an ICommand, which will contain the logic from the OnButtonClick() handler in the simple demo.
I hope that's helpful to anyone else researching this issue down the road.