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.
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.
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.
- 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.
- 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.
- 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.
- 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.
- Create a generic ErrorTemplate that is applied using a style to all standard controls (overriding the default red rectangle around the control).
- Create a new abstract rule class derived from ValidationRule that adds properties for severity and priority.
- 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.
- 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.]
- 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?).
- 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.
- 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!