IDataErrorInfo: confirmation when submitting a page

I am creating a WPF application that will use IDataErrorInfo data that my business objects implement. I worked with this demo from a blog post to understand ValidatesOnDataErrors .

A demo is a trivial application that associates a pair of text fields with a Contact object and implements IDataErrorInfo validation using ValidatesOnDataErrors=True in data binding. To be valid, the text field must contain at least five characters.

Here is my problem: in the demo, the check is performed every time the text field loses focus. In fact, text fields are initialized to an invalid state (red borders) when the application starts. My application should postpone the check until the user clicks the OK button to submit the page. At this time, the text fields should be checked and placed in an error state if they are invalid.

So, how would you postpone checking in text fields until the user clicks the OK button? Thank you for your help.

+4
source share
2 answers

Data binding has the UpdateSourceTrigger property. As the name suggests, it indicates when to update the binding source. For the Text property, this is set to LostFocus by default. You can set this value to Explicit and call the UpdateSource method for the BindingExpression in code. On the other hand, you can also defer raising the PropertyChanged event. However, I think this will not solve the validation problem when the application starts. Hope this helps somehow.

0
source

Thanks to Michael for his help. Unfortunately, I need bindings so that they remain constantly synchronized, and only the check is delayed. Otherwise, Michael's decision will do the job. So, I went in a slightly different direction. Here is the solution that I ultimately implemented.

Simple demo:. Start with the simplest case: my business objects implement IDataErrorInfo ; Let's say I can change the way it is implemented. I give each business object an additional logical property, ValidationEnabled , and I modify the implementation of IDataErrorInfo to always return a null result if this property is false.

The demo that I mentioned in my original post uses a Contact object with two properties; Name and surname. I added the ValidationEnabled property and changed the IDataErrorInfo implementation, as shown below:

 #region IDataErrorInfo Members public string Error { get { throw new System.NotImplementedException(); } } public string this[string columnName] { get { // Initialize string result = null; // Perform validation only if enabled if (ValidationEnabled) { switch (columnName) { // Validate 'First Name' case "FirstName": if (string.IsNullOrEmpty(FirstName)) { result = "First name has to be set"; } else if(FirstName.Length < 5) { result = "First name must be at least five characters"; } break; // Validate "Last Name" case "LastName": if (string.IsNullOrEmpty(LastName)) { result = "Last name has to be set"; } else if (LastName.Length < 5) { result = "Last name must be at least five characters"; } break; } } // Set return value return result; } } #endregion 

In my version of a simple demo, I connect the submit button to an event handler in code that allows you to check and update bindings for both text fields:

 private void OnButtonClick(object sender, RoutedEventArgs e) { var contact = (Contact) DataContext; contact.ValidationEnabled = true; var binding = FirstNameBox.GetBindingExpression(TextBox.TextProperty); binding.UpdateSource(); binding = LastNameBox.GetBindingExpression(TextBox.TextProperty); binding.UpdateSource(); } 

Now the red outlines do not appear until I try to submit the form.

Real world: In my working application, I do not control business objects, and I cannot modify them, as it was in my simple demonstration. Thus, I create a simple end-to-end wrapper for a business object that provides properties for attaching data to a view and associates these properties with the corresponding properties of the wrapped business object. The wrapper implements IDataErrorInfo and contains the ValidationEnabled property.

An IDataErrorInfo shell implementation always returns null if validation is not enabled. If validation is enabled, then the shell calls the implementation of IDataErrorInfo on the wrapped object and returns what it receives from there.

This approach will be familiar to anyone using the Model-View-ViewModel template. What we do is create a wrapper for the presentation model for the business object, which is considered the best MVVM practice for many developers. It separates the user interface problem (suppressing the red borders before the page is sent) for business model reasons (simple object validation).

In addition, my production application will not use encoded event handlers. On MVVM, the button will be connected to ICommand, which will contain the logic from the OnButtonClick () handler in a simple demo.

I hope this helps anyone who tackles this issue in the future.

+7
source

Source: https://habr.com/ru/post/1306214/


All Articles