Sunday, May 28, 2017

wpf, prism, inotifydataerrorinfo and fluent validation

Time for a technical post. Recently my team began work on a new product and the architecture that was selected was WPF, Prism with Unity. Yea I know ..... but we went with WPF because of the intensiveness of the graphics we need to use. The design patterns we choose was Prism with Unity and MVVM. The following samples were taken from efforts to collect data needed to create a connection string for a Maria DB.

As we began looking at a validation implementation, we looked at Fluent Validation. After tinkering around, it seemed very well like by the community and seemed like a great way to manage validation rules.

We started constructing our base class. We created our own ValidatableBindableBase class which which inherits from Prism's BindableBase and INotifyDataErrorInfo. With the INotifyDataErrorInfo, we're implementing the interface with a dictionary, adding and removing items to the dictionary when the DataErrorsChangedEventArgs fires.

So this is the model in which our classes will be built upon. Nothing special, just defining our properties in our model. Notice the model also inherits from our base class - ValidatableBindableBase.

Using Fluent Validation, we created our validation rules based on our model. Fluent Validation makes it incredibly easy to construct rulesets using lambda expressions. Just pass in the entity type to the AbstractValidator base class.

Here I'm showing the view (a partial view of our view) which demonstrates the controls. We are using DevExpress controls here. The controls bind to the viewmodel properties and uses the ValidatesOnNotifyDataErrors attribute set to True. Now the control subscribes to the error raised in the changed DataErrorsChangedEventArgs.

Lastly, the viewmodel. During the construction of the viewmodel, the Save delegate is registered. When the user clicks the save button, the validation is fired. What a joy it was to see the validation fields light up.

It took a little while to get it constructed just right, but I really like this implementation.