Part I: Introducing NHiberate and WPF: The ChinookMediaManager
Part II: Nhibernate and WPF: The core
Part III: Nhibernate and WPF: Models concept
Part IV :Nhibernate and WPF: ViewModels and Views
In this post I will show you an easy way to handle validations in WPF.
In System.ComponentModel we have an interesting interface named IDataErrorInfo.
This interface has two members:
The interesting side of this interface is that if we implement this in our domain classes, the presentation layer will automatically resolved certain things.
Side note: This interface was made with DataTables in mind.
I really like NHibernateValidator, in the same way that I like NHibernate. But, in uNhAddIns we have a main principle: “those two are just options”, so you can change whenever you want to use anything else (Validation Application Block, Validation Framework, Castle Validators, xVal).
For that matter, Fabio Maulo developed a simple interface named IEntityValidator, this is part now of the uNhAddIns.Adapters project. If you want to use Nhibernate Validator the EntityValidator is already implemented here. If you want to use another validator framework please implement the interface and send us the patch ;-).
Implementing IDataErrorInfo directly in domain classes is a waste of time and also is too much invasive, because will end with a dependency in the IEntityValidator. Since we already know how to build injectable behavior we can address this problem in the same way.
I build a new DynamicProxy IInterceptor you could see the implementation here.
The configuration of the Album entity, now looks as follows:
container.Register(Component.For<Album>() .NhibernateEntity() .AddDataErrorInfoBehavior() .AddNotificableBehavior() .LifeStyle.Transient);
The configuration of Nhibernate.Validator is very easy and I don’t want to repeat myself.
Then you need to register an IEntityValidator as follows:
container.Register(Component.For<IEntityValidator>() .ImplementedBy<EntityValidator>());
You have three way to write validations with NHibernate Validator: Xml, Fluent and Attributes. This is aleady very well explained in this post.
In the VIEW the only thing that we need to enable is the ValidateOnDataErrors attribute, this is an example textbox:
<TextBox Text="{Binding Path=Album.Title, ValidatesOnDataErrors=true}" />
I’ve a shared a resource for views, as follows:
<Style TargetType="{x:Type TextBox}"> <Style.Triggers> <Trigger Property="Validation.HasError" Value="true"> <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </Style.Triggers> </Style>
This means: “textbox should display validation errors in tooltip”.
This is all. What?, you don’t believe me.
See the screencast here.
Oh, and I almost forgot, this behavior should also work in ASP.NET Mvc.