In my previous article, 5 Elements of Style For Error Messages, I mentioned you could use the ErrorProvider component to help the user solve a problem by providing an indicator icon and tooltip. In this article, we’ll go over how to use this component.

Why Use ErrorProvider?

It was typical in older applications for a programmer to use a message box to indicate an error condition. This had several problems. First, it interrupted the flow of the program with a modal dialog. Second, it wasn’t easy to indicate exactly which field needed to be corrected. Third, it was tricky to use for multiple entry errors.

What was needed was a better way to validate fields and provide instant feedback to the user as they worked. Some programmers coded this for themselves. Now, the ErrorProvider component does a lot, but not all, of this work for you.

The Basics

The ErrorProvider is simply an indicator for the user in the form of an icon that’s positioned next to a target control. The icon may flash, if desired, and when the user hovers over the icon a tooltip message that describes the problem should appear.

The component is usually found in the Components section of the Visual Studio toolbox. To use it, simply drag it anywhere onto the target form. Since it’s a component, it will reside in the component bar at the bottom of the form designer screen.

The error icon defaults to an exclamation point icon although you can change this if you wish. In the example below, I’ve replaced the default exclamation icon with a friendlier arrow icon. You can also set the icon to blink or not blink. My preference is to not blink.

You can use the SetIconAlignment property to position the error icon relative to the specified control. You can also set the padding value in pixels on a control-by-control basis. This is handy if you need some extra space.

To set an error for a control, you use the SetError method, passing in the control and the error message string. You can clear the error by sending in a blank string. Here’s an example of both.

The matching GetError method allows you to get the specific error assigned to a control. You can use the Clear method to remove all of the currently set error conditions in the object. Unfortunately, this collection of controls and errors isn’t otherwise exposed for you to manipulate.

The ErrorProvider can be used with bound or unbound controls. In this example, I won’t be covering the databinding portion of this component.

The Sample Program

In this example, we’ll use a simple user login setup dialog that an administrative user might use to add a new user or edit an existing user. Our requirements for the form are:

A user name field that must be between 8 and 25 charactersA password field that is between 8 and 20 characters long, that contains at least one upper case letter, one lower case letters, and one numbers or special characters, that uses a password mask character, and that must be entered twice for verification.An Email address field that should be in a valid email address format but should not be more than 50 characters

Here is the basic design:

To meet the maximum length requirements, we’ll simply set the MaxLength property of our textboxes to match. This eliminates the need to check this part of entry. Another trick I like to use is to disable the OK button until all of the entry fields contain valid data. We will see this in action later.

Now, we will need to code our form. To begin with, we will want to set the position of the error provider icon for each control that we want to validate and set the default state. We’ll do this in the Form Load event:

Private Sub frmLoginSetup_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
With erpLoginSetup
.SetIconAlignment(txtUserName, ErrorIconAlignment.MiddleRight)
.SetIconAlignment(txtPassword, ErrorIconAlignment.MiddleRight)
.SetIconAlignment(txtRepeatPassword, ErrorIconAlignment.MiddleRight)
.SetIconAlignment(txtEmail, ErrorIconAlignment.MiddleRight)
End With
'Set the initial state of the error provider
txtUserName_TextChanged(txtUserName, New System.EventArgs)
txtPassword_TextChanged(txtPassword, New System.EventArgs)
txtPassword_TextChanged(txtRepeatPassword, New System.EventArgs)
txtEmail_TextChanged(txtEmail, New System.EventArgs)
End Sub

Next, we will create our validation code. We will begin with the User Name textbox in its TextChanged event:

Private Sub txtUserName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtUserName.TextChanged
If txtUserName.Text.Length < 8 Then
erpLoginSetup.SetError(txtUserName, "User Name must be at least 8 characters long")
Else
erpLoginSetup.SetError(txtUserName, "")
End If
EntriesOK()
End Sub

Now we’ll add code for the password checking. This code is more complex since we’re routing events from both password textboxes through this routine. Note that we’re using a regular expression to test for our strong password so we will want to include an Imports System.Text.RegularExpressions statement at the top of our form module.

Private Sub txtPassword_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtPassword.TextChanged, txtRepeatPassword.TextChanged
Dim txtPwd As TextBox = DirectCast(sender, TextBox)
If txtPwd.Text.Length < 8 Then
erpLoginSetup.SetError(txtPwd, "Password must be at least 8 characters long")
Else
If Regex.IsMatch(txtPwd.Text, "(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$") Then
If txtPassword.Text = txtRepeatPassword.Text Then
erpLoginSetup.SetError(txtPassword, "")
erpLoginSetup.SetError(txtRepeatPassword, "")
Else
If txtPwd.Name = "txtPassword" Then
erpLoginSetup.SetError(txtPassword, "")
erpLoginSetup.SetError(txtRepeatPassword, "Password fields must match.")
Else
erpLoginSetup.SetError(txtPassword, "Password fields must match.")
erpLoginSetup.SetError(txtRepeatPassword, "")
End If
End If
Else
erpLoginSetup.SetError(txtPwd, "Password must contain at least 1 upper case and 1 lower case letter and at least one number or special character.")
End If
End If
EntriesOK()
End Sub

Finally, we’ll add code for the email textbox. Once again, we’re using a regular expression to validate our email address.

Private Sub txtEmail_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtEmail.TextChanged
If Regex.IsMatch(txtEmail.Text, "[a-z][a-z|0-9|]*([_][a-z|0-9]+)*([.][a-z|0-9]+([_][a-z|0-9]+)*)?@[a-z][a-z|0-9|]*\.([a-z][a-z|0-9]*(\.[a-z][a-z|0-9]*)?)$") Then
erpLoginSetup.SetError(txtEmail, "")
Else
erpLoginSetup.SetError(txtEmail, "The provided email address is not a valid email address.")
End If
EntriesOK()
End Sub

Our last routine checks to see if any errors are outstanding. If there aren’t any, it enables the OK button, if there are errors, the button is disabled. This routine should be called from the Text_Changed events that set or clear the provider’s error.