Creating Validator Controls for the CheckBox and CheckBoxList
By Scott Mitchell
Introduction
ASP.NET provides a variety of validation Web controls that can be used to validate a user's form field inputs. (See Form Validation with ASP.NET - It Doesn't Get Any Easier! for general information on the validation Web controls and Dissecting Validation Controls in ASP.NET 2.0 for the validation control changes from ASP.NET version 1.x to ASP.NET version 2.0.) Unfortunately, the validation Web controls do not work with the CheckBox or CheckBoxList Web controls. If you set a validation control's
ControlToValidate
property to the ID
of a CheckBox or CheckBoxList, the page will throw an HttpException
, stating:
"Control 'controlID' referenced by the ControlToValidate property of 'validationControlID' cannot be validated."
There may be times, however, when you need to provide validation for a CheckBox or CheckBoxList. Many Web pages with Terms of Service include a CheckBox titled "I agree to the above terms" that must be checked before continuing. Likewise, a Web Form may contain a set of options in the form of a CheckBoxList. Perhaps the user is required to check at least one of these options before continuing. To provide such validation, we have three choices:
- Forgo any sort of validation Web control semantics and perform the validation check using code on postback. The downside of this is that it breaks from the standard validation control metaphor and requires extra effort to include client-side validation.
- Use the CustomValidator control and define our own server-side and client-side validation logic. The benefit of this approach is that it adheres to the validation control metaphor; however, the validation logic is tightly bound to the ASP.NET page, meaning that the server-side and client-side validation must be replicated on all pages that need to validate a CheckBox or CheckBoxList. (See Using the CustomValidator Control for more information on this topic.)
- Create a custom, compiled validation server control that provides the functionality needed. The benefit of this approach is that we have a reusable, easily deployable custom server control that adheres to the validation control metaphor. Unfortunately, this option requires the most upfront code/effort.
The server controls provided in this article were designed using Visual Studio 2005 and the .NET Framework 2.0's base class libraries; consequently, they will only work in ASP.NET 2.0 applications. If you are still using ASP.NET 1.x, check out Creating a Validation Control for CheckBoxLists. Alternatively, you may adapt the code presented here to work in ASP.NET 1.x.
Creating CheckBox and CheckBoxList Validators in ASP.NET 1.x |
---|
The server controls examined in this article were designed using Visual Studio 2005 and the .NET Framework 2.0's base class libraries; consequently, they will only work in ASP.NET 2.0 applications. If you are still using ASP.NET 1.x, check out Creating a Validation Control for CheckBoxLists. Alternatively, you may adapt the code presented here to work in ASP.NET 1.x. |
Understanding the ASP.NET Validation Workflow
A validation control's primary responsibility is to determine whether or not its assigned control's value is valid. What constitutes validity depends on the validation control - a RequiredFieldValidator, for example, checks to ensure that its control's current value doesn't equal the specified
InitialValue
. Secondarily, validation controls
can be grouped into validation groups, be validated through client script, and so on. Many of these requirements are
provided by properties and methods in the BaseValidator
class (found in the System.Web.UI.WebControls
namespace). Not surprisingly, all of the built-in ASP.NET
validation controls extends the BaseValidator
class, adding their own customizations.
In a short while we'll create our own custom validation Web controls for validating a CheckBox and CheckBoxList. These custom
classes will inherit the BaseValidator
class, overriding the following methods:
EvaluateIsValid()
- this is the onlyBaseValidator
class that must be overridden. It returns a Boolean value that indicates the validation control's validity.ControlPropertiesValid()
- this method returns a Boolean indicating if the control being validated is one that can be. In theBaseValidator
class, it checks to ensure that theControlToValidate
property is set and that the control referenced has a property that can be validated. We need to override this method because this method is the one that throws an exception ifControlToValidate
is set to theID
of a CheckBox or CheckBoxList.OnPreRender(EventArgs)
andAddAttributesToRender(HtmlTextWriter)
- these methods inject client-side script to perform client-side validation (if the user is visiting with an uplevel browser and the validation control'sEnableClientScript
property is True (the default).
CheckBoxValidator
and CheckBoxListValidator
classes. In the CheckBoxValidator
class, we'll add a MustBeChecked
property that indicates whether
the CheckBox needs to be checked or unchecked to be considered valid. In the CheckBoxListValidator
class, the
MinimumNumberOfSelectedCheckBoxes
property indicates the least number of CheckBoxList items that must be selected
for validity. Both controls provide client-side validation support.
The remainder of this article examines the CheckBoxValidator control in detail (the CheckBoxListValidator control is not discussed in this article, but is included in the code available at the end of this download).
The Core CheckBoxValidator Custom Validation Control Members
In both the
CheckBoxValidator
and CheckBoxListValidator
classes I added a protected helper property
to return a reference to the control being validated. Typically, the BaseValidator
class's
GetControlValidationValue()
method can be referenced to get back the value being validated, but with a CheckBox or CheckBoxList, a call to this method
will throw an HttpException
. Therefore, the control value is accessed through the helper property. The following
code shows the CheckBoxValidator
class's helper property and ControlPropertiesValid()
and
EvaluateIsValid()
methods:
namespace skmValidators
|
First, note that the CheckBoxValidator
class extends the BaseValidator
class. Next, examine the
CheckBoxToValidate
property. It uses the FindControl("controlID")
method to find the
control with the specified ControlToValidate
value. If no control with that ID
is found, or if
it's not a CheckBox, the property returns null
.
The ControlPropertiesValid()
method, which is responsible for insuring that the essential validation control
properties are set and are valid, starts by checking the ControlToValidate
property. If it's not specified, an HttpException
is thrown. Likewise, if it cannot find a control with
the specified ControlToValidate
or if that control is not a CheckBox, an HttpException
is thrown.
If those two checks pass, then the method returns True, indicating that the control properties are valid.
The EvaluateIsValid()
method is invoked whenever the validation control's validity needs to be determined.
This method returns True - indicating validity - only if the CheckBox to validate's Checked
property is set
as dictated by the MustBeChecked
property. That is, if MustBeChecked
is True, the CheckBoxValidator
control returns True only if its CheckBox is checked; conversely, if MustBeChecked
is False, the CheckBox must
be unchecked for the validation control to indicate validity.
Adding Client-Side Validation Support
At this point, we have all of the needed server-side functionality for the CheckBoxValidator control. To add client-side functionality, however, we must add a bit more code. The
BaseValidator
class automatically adds client-side
script for handling the plumbing of client-side validation: performing validation when the form submits, determining what
client-side function to invoke for validating each validator, and so on. All we need to do is inject the client-side function
that performs the validation, specify the client-side validation function to invoke, and add any properties needed for
client-side validation to the page's rendered markup (for the CheckBoxValidator control, we need to persist the value of
the MustBeChecked
property to the page's rendered markup to indicate whether the CheckBox needs to be checked
or unchecked to be valid).
These two tasks are handled in two separate methods. The client-side script used for validation should be injected in
the OnPreRender(EventArgs)
method, whereas the name of the validation function and any additional
propeties are added in the AddAttributesToRender(HtmlTextWriter)
method.
Let's start with the OnPreRender(EventArgs)
method. The following code starts by calling the base class's
(BaseValidator
's) OnPreRender(EventArgs)
method, which injects the common client-side script.
Next, the RegisterClientScriptInclude()
method is used to add a script include (<script src="urlToScript" ... />
) to the JavaScript
file embedded within the CheckBoxValidator
class's assembly. (Embedding resources is an easy and efficient means
of deploying and referencing external resource files with a server control library; see Accessing
Embedded Resources through a URL using WebResource.axd
for more information.)
EvaluateIsValid()
methods:
namespace skmValidators
|
The client-side validation function must accept a single input parameter (a reference to the validation control) and must return a Boolean value indicating the validity of the validation control. This function for the CheckBoxValidator control is blindingly simple:
function CheckBoxValidatorEvaluateIsValid(val)
|
The ID
of the control being validated is available via the controltovalidate
property of the
passed-in object; a call to the document.getElementById("id")
function returns a reference to the actual control. The mustBeChecked
property of the validation control
is then accessed. Finally, the function returns True only if the control's checked
property matches up to the
mustBeChecked
property value.
At this point there are two questions facing us. First, how does the common script injected by the BaseValidator
know
to call the CheckBoxValidatorEvaluateIsValid
function to validate the CheckBoxValidator control? And second,
how is the MustBeChecked
property value specified for the CheckBoxValidator control passed to this client-side
function? If you do a View/Source of a page with validation controls on it, you'll find a JavaScript section that spells out
this (and other) information. For example, a RequiredFieldValidator has a select set of its properties rendered in client-side
script like so:
var RequiredFieldValidator1 = document.all ? document.all["RequiredFieldValidator1"] : document.getElementById("controlID");
|
There may be more settings there, depending on what properties you've set for the RequiredFieldValidator, but the concept is the
same - property values needed by the client-side validation logic must be persisted to the client-side through the page's
rendered markup. This includes, at minimum, the ID
of the control to validate and the function responsible for
validation.
This information is injected into the page's rendered markup via the validation control's AddAttributesToRender(HtmlTextWriter)
method, and can be injected in two ways:
- Using the
AddAttribute
method of the passed-inHtmlTextWriter
object. This adds attributes to the validation Web control's rendered HTML element. - Using the
RegisterExpandoAttribute
method, which adds the attributes using client-side script, like in the RequiredFieldValidator script block shown above.
BaseValidator
class adds some of the control's needed state automatically (such as the controltovalidate
)
and chooses which method to use based on the page's XHTML conformance settings. The logic used to determine these settings are,
unfortunately, internal, meaning that they cannot be called from an assebly outside of the .NET Framework. I've attempted to
do my best to replicate the logic in a Helpers
class. The reason this matters is because, in my testing, I found
that for some browsers it was essential that the properties all be defined the same way. Internet Explorer was happy to have
some properties defined using the expando approach, and others as inline attributes, but FireFox wouldn't recognize the inline
attribute values when other values were specified using the expando technique.
Enough minutia, let's look at the code! As you can see below, two attributes are added (either via the expando or AddAttribute
approaches, depending on the Helpers.EnableLegacyRendering()
method's return value). The first attribute is required
and specifies the name of the function to invoke to perform client-side validation. The second attribute persists the
MustBeChecked
property to the rendered output.
namespace skmValidators
|
Using the CheckBoxValidator and CheckBoxListValidator Controls
To get started using the CheckBoxValidator and CheckBoxListValidator controls in your ASP.NET 2.0 web application, download the code at the end of this article and drop the
skmValidators
assembly into your application's /Bin
folder. You can add the validation controls to Visual Studio 2005's Toolbox - right click on the Toolbox, select Choose Items
and browse to skmValidators.dll
- or you can manually add the controls using declarative markup and the
<%@ Register %gt;
directive.
Once you've added the controls to the Toolbox or have entered their markup manually, they should appear as any validation control when in the Designer. Moreover, their properties should be accessible through the Properties window. And most importantly, when visiting a page through a browser, they should function as expected!
The CheckBoxValidator in the Designer in Visual Studio

The CheckBoxValidator When Viewed Through a Web Page

At the end of this article you'll find links to related articles, the complete project code that includes a test project with a demo page. In this article we only examined the CheckBoxValidator control; the download includes an additional validation control designed to work with CheckBoxLists.
The CheckBoxValidator Control Has Been Upgraded! |
---|
I have upgraded the CheckBoxValidator so that it can optionally enable or disable an associated Button, LinkButton, or ImageButton control depending
on its CheckBox's checked state.
![]() For more information, see Disabling the Submit Button Until a CheckBox is Checked. |
Happy Programming!
Further Readings:
WebResource.axd