Previous
Chapter XIII

The series

WCF by example is a series of articles that describe how to design and develop a WPF client using WCF for communication and NHibernate for persistence purposes. The series introduction describes the scope of the articles and discusses the architect solution at a high level. The source code for the series is found at CodePlex.

Chapter overview

This is a two part chapter that covers the validation in WPF views and the management of business exceptions and warnings in the client side. For the validation topic, we will discuss how to provide comprehensive validation functionality all the way from the UI layers back to the server side, for the warnings and exceptions, the application will provide a customised exception handling mechanism for both client exceptions and business exceptions returned by the server methods; for the business notifications we will put in place a nice and slick notification feature that uses balloon notification messages in the Windows Task Bar.

Only the first part of this chapter, the validation, is included so far, we will amend the chapter with the second part as soon as possible.

Validation - DTO Implementation

We haven't covered validation in WPF in the series so far, maybe the reason for so it is to do with the fact that WPF validation is not that straight forward. We are going to describe what we consider to be a comprehensive solution given our application design. The eDirectory's solution is a hybrid one where a rich UI experience is provided but the validation code is not placed in the business entity, instead the DTO class is used for that purposes. In a nutshell, the following is an example of the type of validation functionality that is achieved in this manner:

In order to provide the above functionality the following steps are required:

  • The DTO class needs to inherit from a new base class: ValidatorDtoBase
  • DataAnnotation attributes are added to the DTO properties for validation purposes
  • XAML Binding needs to be amended with the following:
    1. Mode = TwoWay
    2. ValidatesOnDataErrors = True
    3. Validation.ErrorTemplate is set to the validationTemplate
  • Command buttons can bind to the IsValid property in the DTO for enabling/disabling purposes

As an example of how the DTOs will look after the above indicated changes, the CustomerDto looks like:

And the following is a section of the XAML that was changed:

And the last change is in the ViewModel so the Save button is enabled only when there are not validation errors:

Validation Design Discussion

Before we continue, lets stop for a second to discuss what goals we tried to achieve with the above mentioned solution:

  • Follow the DRY principle
  • Easy to test
  • It should be possible to execute the validation both in the server and the client side

Regarding the DRY principle, on paper, the business entity should be responsible for the business validation, in the case of the eDirectory Customer class, for example, the First Name field is not nullable and cannot be longer than 50 chars. This is a classic example of validation that should be defined on the entity itself. It is feasible placing this validation on the entity but it generates a sort of crude validation solution where the client needs to call the server to find out if there is validation errors. On some projects this is acceptable and it may result in being the best approach as it facilitates testing and rapid development.

The eDirectory application proposes a solution where simple validation can be declared in the DTO object so WPF validation can be used in the client side, the entity can also use this validation in the server side. We are basing this solution in the following articles:

Attributes-base Validation in a WPF MVVM In this article the IDataErrorInfo interface is used in combination with validation attributes in the ViewModel classes. We used the logic in the back-end to retrieve validation attributes and getters using LINQ queries. This concept was originally covered on the WPF Validation with Attributes and IDataErrorInfo in MVVM post
Automatically validating business entities in WPF using custom binding and attributes This is an interesting article by Sandrino Di Mattia based on the work done by Phillipp Sumi on WPF custom binding. In this solution a custom WPF binding is used for validation purposes, the eDirectory solution is very similar but it is developed around standard classes without requiring additional implementation. Still, it is a very good article.
Validation in Windows Presentation Foundation This is a four year old article that still applies, it is surprising how little things have changed since then, maybe MS is trying to say to all of us that is time to move to the mighty SilverLight :)
Implementing Data Validation in Silverlight with INotifyDataErrorInfo This article covers the use of INotifyDataErrorInfo in silverlight. It is a good article, discussing the limitations of the IDataErrorInfo interface and covering some of the internals of how controls interacts with the validation code.

Before we move on, if you are one of those that like DDD and find frustrating to locate the validation outside the business entities. It may be the time to look at frameworks that resolve this type of issue in a better way:

IDataErrorInfo & Validation Attributes Implementation

The eDirectory solution is based on the proposed idea on the WPF Validation with Attributes and IDataErrorInfo interface in MVVM post and it states:

WPF provides validation infrastructure for binding scenarios through IDataErrorInfo interface. Basically you have to implement the Item[columnName] property putting the validation logic for each property in your Model (or ModelView) requiring validation. From XAML you need to set ValidatesOnDataErrors to true and decide when you want the binding invoke the validation logic (through UpdateSourceTrigger). Then idea is to generalize the validation logic in IDataErrorInfo.Item[] using the validation attributes in System.ComponentModel.DataAnnotations assembly.

So we can have a new base class that inherits from DtoBase and implements the IDataErrorInfo interface so the WPF control can be notified if there was a validation error. The base class delegates to an instance of DataErrorInfo which is responsible for gathering the properties that are tagged with validation attributes and invokes the validation when the IDataErrorInfo methods are executed.

It is worth noting that both the ValidatorDtoBase and DataErrorInfo implement the IDataErrorinfo interface and that the first one merely delegates into the second class when the methods are invoked.

There is one aspect on this class that can be improved in terms of performance, your Dtos will not change at run time so it probably makes sense to store the validator and property maps the first time that they are created. This will result in a performance improvement although you will have to watch out for synchronization issues and locking.

Server side validation

As we indicated at the start of this chapter, one of our goals is to be able to check for validation errors at the server side as well. With the proposed solution is relatively easy to achieve this requirement. For example, when the Customer.Create method is invoked the following code has been added:

The ValidateOperation method is declared in the base class: EntityBase, this method check for validation errors in the DTO, throwing a business exception if any error is found:

XAML Error Templates

WPF provides very basic support for validation errors on the views, however with some few changes we can provide a richer experience. Our solution provides three different mechanisms: red border around the textbox control, validation error symbol and tooltip.

For the red border and the validation error symbol a control template was created named validationTemplate, for the tooltip a custom style was created for the TextBox control. Both declarations were added to Application.resources at the App.xaml file.

For the tooltip to be shown no further action is required. However, we need to indicate in each control that we want to use the validationTemplate in the XAML. You may prefer to move this template to an style instead, the following article explains how to do it: IDataErrorInfo, Error Templates and WPF

The XAML for the template and style is as follows:

Chapter Summary

Validation in WPF could be cumbersome sometimes, in this chapter a comprehensive solution using Validation attributes was presented that permits execute the same validation both in the client and server side thus providing easy testing even the validation logic is not located at the business entities.

We will soon amend this chapter with the second part regarding exception and warning management implementation, in the meantime, the code at CodePlex has been updated with the Validation and exception management functionality.

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架