Validation Toolkit for WPF & Silverlight displays automatically validation errors coming from both Data Annotations on the View Model and Asynchronous calls to Web Services. The View Model is wrapped into an object that supplies all needed interface implementations.
Main object of the project
Enabling programmers to keep the plumbing logic needed to propagate validation errors to the User Interface as separate as possible from the Business logic, and to reduce as much as possible the code needed to perform data validation. We have chosen to use
Data Annotations as the main source of validation errors because they rely on a declarative model and keep the validation code completely separated from the business logics. Another source of validation errors we allows is Validation Exceptions coming from
web services once the request is submitted to the server, Web services may produce such Validation Exceptions either through data annotations in other business classes or through the interaction with data sources.
You can find documentation
here, a description of the examples included in the distribution
here, and tutorials in the
Data Validation Series of posts in my blog, and about Silverlight/Server communication(here and
- Validation Toolkit for WPF & Silverlight handles both data annotations and validation exceptions coming from web services
- Web services may be called also asynchronously: the user interface is updated when validation exceptions come.
- Validation Exceptions specify the piece of View Model they apply to, and Validation Toolkit for
WPF & Silverlight uses this information to display them adequately
- Validation Exceptions come either from Data Annotation on the server side or from the interaction of the business level with data sources.
- The interface offered to the programmer by both the Silverlight and the
WPF versions is the same in spite of the different techniques used by the two versions to communicate with the presentation layer.
- The View Model that is bound to the user interface doesn't need to implement ANY interface, Validation Toolkit for WPF & Silverlight deso all the job for it.
- No need to implement INotifyPropertyChanged: Validation Toolkit for WPF & Silverlight does it for you
- No need to implement INotifyDataErrorInfo or IDataErrorInfo: Validation Toolkit for WPF & Silverlight does it for you
- Helper methods to pack properly Validation exceptions on the server side
- Endpoint Behavior to enable the Wcf endpoint to be used by Silverlight to communicate FaultExceptions whose details are accessible by the Silverlight client(see the "How to use it" section below for more explanations, and see here
for a discussion about this problem).
- Observable Dictionary datatype to handle adequately dictionaries, too.
- FormatError attribute to specify errors in case wrong formatted string are inserted by the user.
- The whole tree structure of the View Model is enabled to send errors and property changed events to the UI: collections and dictionaries at any depth included.
- DynamicRangeAttribute that extends the standard RangeAttribute
by allowing both Min and Max be object properties at any level in the objects subtree (the same syntax for specifying properties in bindings apply). Moreover, a Dynamic Delay can be applied to both Dynamic Minimum and Dynamic Maximum.
- DynamicAttribute. Base attribute for defining dynamic attributes as the DynamicRangeAttribute.
If the Validation Toolkit for WPF & Silerlight was useful to you, consider doing a donation, to support it!
How to use it.
Using Validation Toolkit for WPF & Silverlight is very easy:
- First, you have to enable ValidatesOnNotifyDataErrors in Silverlight and
ValidatesOnDataErros in WPF for the bindings you want to apply validation to.
- Then, you need to wrap your View Model into the dynamic object BindWrapper with the instruction: new BindWrapper(ViewModel, true, true); Setting the second parameter to
true causes all son objects of the View Model be recursively wrapped, too. Recursive wrapping will continue also through the boundaries of
IEnumerables if the third parameter is set to true .
- If there is no top level View Model class but your top level structure is either a simple enumerable or a dictionary you can wrap recursively through them by calling respectively:
static ObservableCollection<BindWrapper> WrapEnumerable(IEnumerable source, bool wrapDeep = false, bool wrapEnumerables=false)
public static ObservableDictionary<string, BindWrapper> WrapDictionary<TValue>(IDictionary<string, TValue> source, bool wrapDeep = false, bool wrapEnumerables = false)
The result is respectively either an observable collection or an observable dictionary(the observable dictionary type is implemented in the toolkit). The meaning of the parameters is the same as the ones of the BindWrapper constructor.
- Use the wrapper in place of your original object. You can get or set a property of your original View Model by getting or setting a property of the wrapper with the same name: It is a dynamic object it will accept it, and it will retrive or update
the original property of your View Model while triggering the adequate events to update the interface and to perform validation.
- Bind the wrapper to your user interface. In Silverlight you need to enclose in square brackets the names of the properties in your Bindings, because Silverlight doesn't support dynamic object and we were forced to use a dictionary. For instance, [Age] instead
of Age. In WPF you can write the names of the properties as if they would come from your original View Model.
- Validation of the simple properties is done automatically. When you want to trigger object level validation on the whole View Model or on a part of it, you call the
ValidateWholeObject method of the relative wrapper. If Some Validation Exceptions are already available you can pass them to
ValidateWholeObject as a parameter.
- Each time Validation Exceptions comes from a web service you can call AddValidationFaultExceptionContent(IEnumerable<ValidationErrorInfo> errors) to update the interface. Where
ValidationErrorInfo is a class used by the server to pack all server side errors into a
FaultException<IEnumerable<ValidationErrorInfo>>. Please note that a Wpf client can receive the details of this
FaultException only if the interface that defines the service is decorated with the
[FaultContract(typeof(IEnumerable<ValidationErrorInfo>))] attribute. In case of a Silverlight client we have also to define a Silverlight specific endpoint and a apply to it the endpoint behavior included in the toolkit, that in case
of exceptions, updates the status code of the response to 200 because Silverlight being a plugin can receive the deail of a response only if the status code of the response is either 200 or 404. See the example included in the binary distribution for details
about how to configure the Silverlight endpoint.
- If for some reason you need to reset the interface from object level validation errors you can call ResetGlobalEvaluation(), but normally you don't need to do it.