Click here to Skip to main content
Click here to Skip to main content

Validizor - A Validation Control for WPF

, 17 Oct 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
A WPF validation control for validating your data objects.
Screenshot - validizor1.gif

Introduction

Validizor is a WPF control that can be used to validate objects and their properties. When validation fails, a Validizor displays an error icon with the error message(s) in a tooltip.

This article explains the advantages of using Validizor and how to use it. To see Validizor in action, download the demo executable and give it a try!

Background

WPF offers validation in its Binding.ValidationRules, but these associate validation rules with UI controls. This is undesirable because sometimes an application allows the same data to be entered in more than one screen. Validation rules would need to be duplicated for each screen. It seems more logical to keep your validation rules with your data objects.

Microsoft's Enterprise Library Validation Application Block (VAB) allows validation rules to be associated directly with your data objects, but Microsoft does not currently offer a WPF control to take advantage of it.

Validizor leverages Enterprise Library's VAB to offer data object validation packaged in a WPF control. VAB comes with a nice assortment of Validators allowing you to build validation rules involving string lengths, enums, numerical ranges, regular expressions, object types, nulls, and more.

Benefits

  • Unlike WPF's Binding.ValidationRules which define validation rules in your UI's XAML, Validizor uses Enterprise Library's VAB. This means your validation rules are directly associated with your object classes and their properties. Plus you can use the Validators that VAB comes with.
  • WPF's Binding validation will not set a value into your source object when its Binding.ValidationRules fail. Validizor WILL set invalid values into your objects. This allows you to easily retain erroneous data during user editing, yet gives you a mechanism to avoid using/committing it before they are corrected.
  • WPF's Binding does not perform validation when a window/control first loads. The Binding ValidationExample at MSDN demonstrates this. Initial values aren't validated. A Validizor validates its data when it is loaded and whenever the source value changes.
  • All the examples I've seen that use WPF's Binding validation target a TextBox. When there is a validation error, the TextBox's ToolTip is set to the first validation error. None of the examples ever mention the fact that now you've overwritten any ToolTip that may have been on the TextBox in the first place. Whoops! Validizor uses its own ToolTip which displays all the invalid validation rules for the source object, not just the first.

Using the Code

Simple Example

Here is a quick demonstration of using a Validizor. You really should download the demo application for a more complete example.

In a simple scenario, you might have a Person object with a FirstName property. A validation rule could be defined as an attribute on FirstName like so:

[StringLengthValidator(1, 15, MessageTemplate = 
    "First Name must be between 1 and 15 characters", Ruleset = "Default")]
public string FirstName
{
...
}

In your XAML, you might have a TextBox bound to this property, along with a Validizor:

<StackPanel Orientation="Horizontal" >
    <TextBox Text="{Binding Path=FirstName, 
        UpdateSourceTrigger=PropertyChanged}" />
    <val:Validizor Source="{Binding Path=FirstName}" Ruleset="Default" />
</StackPanel>

The result would be a UI that shows the invalid values while you enter them:

Screenshot of a simple example

Validizor Properties

An instance of Validizor can be configured through its properties:

  • Source: This is a dependency property of type object and should be bound to the data being validated. By default, Validizor will assume Source is a property of some object. It will use the validation rules that target the property, defined for the "owner" object . Validizor will use the Source binding's Path to find the Type of the "owner" object, allowing it to use the validation rules that target this object's property. In some cases this behavior is not desired and/or the Validizor cannot obtain the "owner" object based on the binding to Source. In these cases, the Validizor has other properties that can be used (as explained below). In any case, Source must be bound to a source object that will be validated.
  • SourceOverride: This property can be used to override the Validizor's behavior of automatically using the Source binding to find the "owner" Type. In some circumstances the "owner" object's Type cannot be obtained by using Source's binding Path. SourceOverride can be used to directly specify OwnerType and PropertyName. When these are defined, Validizor will use OwnerType as the type of the "owner" object, and PropertyName as the name of the property being validated. It will still use the Source value as the value to validate. The demo application demonstrates this.
  • ObjectValidation: This property is a boolean and defaults to False. When set to true, Validizor will no longer look for the validation rules within the "owner" object. Instead it will treat the Source value as an object that can be validated by itself. The demo application demonstrates this also.
  • Ruleset: This property is a string that indicates the ruleset to validate with. Enterprise Library VAB validation rules can be labeled with a ruleset. This allows you to put multiple rules on individual properties and objects that will only get evaluated when a specific ruleset is being targeted.
  • RuleSource: This property is a string that indicates the Enterprise Library VAB ValidationSpecificationSource. It defaults to "Both." "Attributes" indicates that only the validation rules defined within the source code should be used. "Configuration" indicates that only the validation rules defined in App.config should be used. "Both" indicates that validation rules from both attributes and App.config should be combined and used.

Helper Methods

Validizor also offers several static helper methods for validating lists of objects and for formatting validation results. These can be used for validating the data objects in your code-behind, for example, when a user clicks a "Submit" button to save the data he/she has edited.

Points of Interest

Enterprise Library Validation Application Block (VAB)

In order to use Validizor, you'll need to install Microsoft Enterprise Library 3.1. Once it is installed, you will be able to add References to Microsoft.Practices.EnterpriseLibrary.Validation in your projects. This will allow you to take advantage of the existing Validators when defining your validation rules. It also allows you to edit your App.config (if you choose to put rules there) using the Enterprise Library Configuration Editor.

VAB validation rules can be defined in two places. The Enterprise Library comes with a configuration editor to easily define validation rules in your App.config. Alternatively, as I did in the demo application, validation rules can be defined directly in your classes as attributes. Either way, this is a feature of the VAB, and Validizor simply takes advantage of it. The VAB has a good variety of Validators from which to base your rules, and is in active development at the time this article was written.

Enterprise Library Validation integration with WPF

Martin Bennedik has written a library to integrate Enterprise Library Validation with WPF. Validizor leverages Martin's work, but uses its own versions of his code, as a few modifications were necessary.

Invalid Type Issue

As mentioned before, one of the benefits of Validizor over Binding.ValidationRules is that it allows invalid values to be set in your data objects. But what it can't do is set values that cannot be converted into the type of the source object. For example, if a DateTime object is bound to the Text of a TextBox, the user would be capable of typing in gibberish. Text such as "Blah blah blah" cannot be converted into a DateTime and so WPF binding will not be able to set the DateTime property in your data object. One way to make this a moot point is to use controls that only generate appropriate objects/values. In the demo application, a DatePicker control is used to guarantee that a valid DateTime is always entered by the user. But you will see that the demo application also demonstrates this issue in its "Hair Count" TextBox.

Knowing When Properties Within an Object Changed

If your class implements INotifyPropertyChanged, and you instrument your property setters, binding will know when a property value has been changed. But if your property is an object itself, then binding won't know when a property WITHIN that object has changed. I wish there was a better mechanism for this built directly into the .NET framework. For now, one solution I like is Josh Smith's BusinessObjectHolder generic class. I have used it in the demo application.

History

  • October 2007: Initial creation

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Buzz Weetman
Software Developer
United States United States
software engineer

Comments and Discussions

 
QuestionVS2008;PropertyComparisonValidators and self Validations? [modified] Pinmemberbannont27-Dec-08 8:18 
AnswerRe: VS2008;PropertyComparisonValidators and self Validations? PinmemberBuzz Weetman27-Dec-08 11:29 
GeneralRe: VS2008;PropertyComparisonValidators and self Validations? Pinmemberbannont27-Dec-08 12:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.141015.1 | Last Updated 17 Oct 2007
Article Copyright 2007 by Buzz Weetman
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid