Validation in Windows Forms

by Scosby Thursday, February 11, 2010

Validating user input should belong in every developer’s tool kit. Today we will look at how Windows Forms applications should accomplish this task.

The main pattern for validation is event driven. The two events we will use are Control.Validating and Control.Validated. To begin, let’s create the simple WinForms application shown in Figure 1.

Figure 1 – a simple application

Let’s add one more component to spice up the UI. Open your toolbox and add an ErrorProvider control onto the form as shown in Figure 2. The ErrorProvider component will display a nice icon and tooltip next to the control, if it fails validation.

Figure 2 - adding the ErrorProvider

Let’s assume when we click our save button that we wish to validate the controls and display an icon if there is a problem. First, add the following code to the Form’s constructor after the InitializeComponent method:

        this.AutoValidate = System.Windows.Forms.AutoValidate.Disable; 

This is a handy trick to prevent implicit validation of our controls when they lose focus. You do not have to disable the Form’s AutoValidate property. However, I prefer to call it explicitly and handle all validation at once since you most likely will take action only if the entire control’s children pass validation.

Next, we need to wire up the save button’s click event. Here is the code for that event handler:

        private void buttonSave_Click(object sender, EventArgs e)       
       
{
            if (this.ValidateChildren(ValidationConstraints.Enabled))
            {
                MessageBox.Show("All controls are valid!");
                 //Logic to save...
            }
            else
            {
                MessageBox.Show("There are invalid controls on the form.");
                 //Return user to form...
            }
        }

Notice how we simply call the Form.ValidateChildren method telling it to only validate enabled controls with the ValidationConstraints.Enabled enum? The ValidateChildren method will raise the validating events for all child controls in the container and this is known as explicit validation.

Next, let’s create the Validating and Validated event handlers for both of our textboxes. The first textbox will be the Number. Here are the two events:

        private void textBoxNumber_Validating(object sender, CancelEventArgs e)
        {
            bool cancel = false;
            int number = -1;
            if (int.TryParse(this.textBoxNumber.Text, out number))
            {
                if (number > 0 && number < 11)
                {
                    //This control passes validation.
                    cancel = false;
                }
                else
                {
                    //This control has failed validation: number is not in valid range
                    cancel = true;
                    this.errorProvider1.SetError(this.textBoxNumber, "You must provide a number between 1 and 10!");
                }
            }
            else
            {
                //This control has failed validation: text box is not a number
                cancel = true;
                this.errorProvider1.SetError(this.textBoxNumber, "You must provide a valid number!");
            }
             e.Cancel = cancel;
        }

        private void textBoxNumber_Validated(object sender, EventArgs e)
        {
            //Control has validated, clear any error message.
            this.errorProvider1.SetError(this.textBoxNumber, string.Empty);
        } 


Let’s address the Validating event first. The most important thing to recognize here is how precise you can be with the validation error message in the error provider. There are 2 code paths for validation failure, and in each case we provide the user with an appropriate error message. The error provider simply takes a control and a message in the SetError method and does the rest of the work for you! If the user enters invalid data they’ll see an icon shown in Figure 3.

Figure 3 - error provider icons

After the validating event returns without being cancelled, meaning we have valid user input, then the validated event will be raised. In this case, we simply clear any error messages in the error provider.

The Name textbox works very similarly but we don’t have quite as elaborate validation logic. The validated event works the same, only pass it the name textbox instead. Here is just the validating event handler’s code:

        private void textBoxName_Validating(object sender, CancelEventArgs e)
        {
            bool cancel = false;
            if (string.IsNullOrEmpty(this.textBoxName.Text))
            {
                //This control fails validation: Name cannot be empty.
                cancel = true;
                this.errorProvider1.SetError(this.textBoxName, "You must provide your name!");
            }
             e.Cancel = cancel;

                 }


The event driven validation model in WinForms is powerful and flexible enough to allow you to create high quality apps that implement robust and maintainable validation code in your forms. Now practice your newly learned skills on your own and experiment with the error provider control!


You can read more about
user input validation in Windows Forms at MSDN.

Tags: ,

Programming

blog comments powered by Disqus