Validation Engine

I’ve now had a chance to play with many (all?) of the Validation classes in WPF under .NET 3.5 and here is a brief summary of my findings thus far.

Binding Contains the ValidationRules property which is a collection of rules that apply to and are triggered by that binding.
Also has properties to apply “standard” validation rules, being ValidatesOnDataErrors and ValidatesOnException.
Setting NotifyOnValidationError=”True” is required in order for the attached Validation.Error event to be raised.
ValidationRule Abstract class that forces derived classes to implement a Validate method. This is pretty straight forward and works well in that it returns a ValidationResult which is easily extendible.
ValidationResult Contains an ErrorContent property defined as object that allows rich validation errors to be returned.
DataErrorValidationRule Allows validation to be performed via the IDataErrorInfo interface on the binding context (assuming it implements it).
Equivalent to setting ValidatesOnDataErrors=”True” on the Binding.
ExceptionValidationRule Converts binding exceptions into validation errors. Can’t see this as being the primary approach to validation – but does provide a useful method for catering for real exceptions.
Equivalent to setting ValidatesOnException=”True” on the Binding.
Validation Static class that provides some important attached properties (Errors, ErrorTemplate and HasError) and an attached event (Error).
ValidationError Represents an error that has been generated by a ValidationRule or manually created via a call to the MarkInvalid method.
It links the Binding, ValidationResult’s content and Rule together and is passed to the attached Validation.Error event to allow subscribers to perform related actions – e.g. log the error, display errors in a status panel, enable/disable controls.
IDataErrorInfo

Allows custom data classes to express data errors at an instance and/or field level. Whilst great in theory the real flaw (in my opinion) with this interface is that it only allows those errors to be expressed as strings.
This is limited because:

  1. We need to be capable of raising rich error information – for example – nominating the severity of the error, link to online help for further details or related content, provide access to automated response – e.g. apply default value. Sure we could embed an XML fragment describing richer content – but wouldn’t it have made more sense for this to be an object – even if the default controls simply performed a ToString() for their own limited error display?
  2. What if two fields combine to generate an error where their values conflict with one another. You can generate an error string for each but there really isn’t any neat way of associating them.

So what do I think a Validation System should provide? Here’s my required feature list drawing from my own experience of using these types of engines as the sole means for validating complex form data.

  1. Capable of highlighting controls that contain data which is in error, i.e. from something as simple as WinForm’s ErrorProvider through to WPF’s ErrorTemplate.
  2. Allow for multiple levels of validation severity. For example – the validation system should be capable of displaying not just errors, but warnings and even hints/suggestions.
  3. Allow for multiple level of validation priority. If multiple errors are raised the priority can be used to determine the order in which an error summary is built and displayed to the end-user – for example displaying only the highest priority message within a status panel.
  4. Simple validation logic should be defined wherever possible from property meta-data. For example, if a property is required to have a value an appropriate rule should be automatically applied (e.g. RequiredRule). For a rich data model this could include ranges (dates & numbers), numeric precision and string lengths.

Some ideas on how these requirements could be implemented with/around the WPF validation model.

  1. Create a generic ErrorTemplate that is applied using a style to all standard controls (overriding the default red rectangle around the control).
  2. Create a new abstract rule class derived from ValidationRule that adds properties for severity and priority.
  3. Create a new ValidationContent class that allows for rich error  information to be returned in a ValidationResult and becomes the object stored in ValidationError.ErrorContent.Error.
  4. Create a new interface IDataValidationInfo (?) that replace IDataErrorInfo exposing ValidationContent objects rather than just strings. [At the same time it should provide a method of being backwards compatible with IDataErrorInfo classes.]
  5. Create custom attributes that allow property meta-data to be defined within class models. Allow for automatic generation of rules based upon this meta-data (during Binding initialisation?).
  6. Use the Validation.Error attached routed event to automatically subscribe to all a containers validation. This is then used to display validation summary information within a status panel.
  7. Associated commands with rules – so that validation errors can be used to present the user the option of executing these commands.

At this stage this is all pretty “pie in the sky” stuff. Over the next couple of weeks I hope to post a few examples of some of this in action!

2 thoughts on “Validation Engine”

  1. Hi Nigel,

    I like where you are going with the validation system. I’ve dealt with similar issues recently putting together basic validation handling in a new project.

    As a suggestion, I found it useful to have the validation system output a collection of ValidationResult objects – one for each failed rule. The ValidationResult has a PropertyName string describing the property with the error and an ErrorDetail object containing the specifics. The standard IDataErrorInfo interface can then be implemented by looping through the collection concatenating ErrorDetail.ToString() for each item into separate lines in a StringBuilder. The PropertyName can be used to filter only certain results as required by the interface.

    Regards,


    Jason Stangroome

    PS: I’d like to invite you to an upcoming Adelaide .NET Dinner (see my blog for details) but couldn’t find your contact details. Send me an email if you’re interested.

Comments are closed.