Introduction

ASP.NET provides a mechanism to validate user input. That is, before a user submit his/her page, there are several kinds of validators that validate the input. However, in WinForms, we can't get those excellent components. When we validate a text in a control, for example, there is a TextBox named "txtPassword", and it requires users to input a password text beginning with a letter and having 3-8 length numbers or letters, we must register txtPassword's Validating event, and the event method should like:

It's really a dull assignment, and if there is a lot of controls in your form, it makes maintenance difficult. My goal is to validate controls without any code! With Validator, you drop it to a form and enter the validation rules for a TextBox or a ComboBox just like using the ToolTip component.

Background

I got the afflatus from the following article but implement a different approach. I suggest you read it:

Using the code

First, create a new Windows Forms application, and follow these steps to use the Validator component:

Add assembly

Open the "Toolbox" window, right click in the "General" tab, and click "Choose items...".

If you have strong named Validator assembly and has added it to the GAC, you can choose it in the ".NET Framework components" list. Or else, in the example, click the "Browse" button and locate your Validator.dll assembly.

Now, you can find it in "Toolbox".

Add and configure the component

Drag the Validator which has been added by the first step, and drop it on the form. Its property window should be like:

The important properties for this component are:

Form - specify a form where validated controls lay onto. Validator will register its FormClosing event, validates controls, and decides whether to close the windows.

Mode - this enum value can been one, or combined by FocusChange and Submit. FocusChange means when validating a control fails, the focus stops on that control or is changed to the next tab index control; Submit means that validate controls while the form is closing, and prevent the form from closing when the validation fails.

BlinkRate, BlinkStyle, Icon, RightToLeft: same as ErrorProvider properties, please use MSDN for help.

Configure the TextBoxes and their properties

Now we will assume that there are three TextBoxes and one Submit button on the form.

Name

Text

Properties

Function

txtName

User name, required input.

txtPassword

PasswordChar = "*"

Input password, begins with an alphabet and has 3-8 numbers or alphabets.

txtRePassword

PasswordChar = "*"

Re-input password, same as password.

txtSubmit

Submit

DialogResult = OK

Submit and close form.

Configure validation info for the controls. Now, configure txtRePassword for the demo: show the txtRePassword property window. You will surprisingly find an extra category, "Validation", there:

Type: dropdown the "Type on validator1" item and select the Required and Compare items.

RequiredMessage: input - "Please input re-password.".

ComparedControl: dropdown and select "txtPassword".

CompareOperator: dropdown and select "Equal".

CompareMessage: input "Re-Password not same as password".

The extended properties should be like the following table (omit message):

Congratulations! You got to the point of using the Validator. Run your form, and when you enter an invalid value in the TextBox, it will show an error message. You click the "Submit" button, it will not close the window while there are still errors. For a full demo, I have got a "register" example for you, please analyse it yourself. If you have any problems, feel free to contact me.

Points of Interest

In this section, I want to say more about advanced components programming. It will be a guide to people who are interested in my Validator component and will show the key points of the Validator. Here, I will assume you that have basic components programming skills, like creating a component class, applying DefaultValue, DefaultEvent, and Browsable attributes, and so on.

Extend property

ErrorProvider, ToolTip, and Validator - these components provide a mechanism which extends controls' (or components') properties, in the property window. You will see text like "Type on validator1", which means Type property is an extended property and is provided by the validator1 control (or component). To have this amazing feature:

The component must implement the IExtenderProvider interface.

publicpartialclass Validator : Component, IExtenderProvider

IExtenderProvider has an abstract method that must be implements (from MSDN):

CanExtend: Returns whether or not the provider can provide an Extender for the given object in the specified category.

When you edit the ForeColor property for a TextBox in the property window, it drops down a Color Editor dialog.

When you edit the Lines property for a TextBox in the property window, it shows a String Collection Editor dialog.

Actually, a property window only provides a simple text input editor as default. How do Color and Lines properties do this? Using the Reflector v4.2 to disassemble the System.Drawing.Color struct in the System.Drawing.dll assembly, we find this struct that applies the Editor attribute.

[Editor("System.Drawing.Design.ColorEditor, ..."]

Disassemble the System.Windows.Form.TextBoxBase (TextBoxBase derives from TextBox) class in the System.Windows.Form.dll assembly, and we will find that the Lines property applies the Editor attribute.

[Editor("System.Windows.Forms.Design.StringArrayEditor, ..."]

The Editor attribute can be applied to either a class (struct) or a property. If class A applies the Editor attrubute, any other class can define properties of class A. Those properties will always be edited by the specified editor in the property window.

Only those properties which apply the Editor attrubute will be edited by the specified editor; although other property types are same, they will be edited by the default simple text box.

In the Validator project, I wrote a FlagEditor class, and it can edit the Flag enum type. Like the RegexOptionsenum, you can choose the bit value set using | (logic OR), or click the "None" button to set enum value to 0.

To implement the Editor attribute, the class must derive from UITypeEditor:

publicsealedpartialclass FlagsEditor : UITypeEditor

and override the EditValue and GetEditStyle methods. For details, you can refer to MSDN.

First, it asserts that we can only edit the enum type with Flags attribute. Secondly, it drops down a user control which has a "None" button to set the enum value to 0, and has several check list items each of which represents one enumeration member except "None".

Component Designer

Have you noticed that, if you set the focus on a ListView control at design time, there appears a triangle button on it. When you click it, it will show a context menu.

Besides, when you drop a ErrorProvider to a Form, it will automatically generate a line like:

this.errorProvider1.ContainerControl = this;

How does C# do that? In Validator, I apply the Design attribute:

[Designer(typeof(Validator.ValidatorDesigner), typeof(IDesigner))]

ValidatorDesign derives from ComponentDesign which provides an approach to above issues. ComponentDesign has a virtual property ActionLists, which returns a menu like the ListView control, and has a virtual method InitializeNewComponent telling the IDE how to generate code.

History

April 11th, 2006 - First version.

Thanks to

Michael Weinhardt, for his article in MSDN.

Bo Shen, who checks my article and corrects my English.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.