Wednesday, August 13, 2008

CheckBoxList Validation - Validator for CheckBoxList control in Asp.Net

Download
See the link below to download the control

Introduction
The ASP.Net Validator controls shipped by Microsoft .Net Framework (from 1.0 till 3.5) are very helpful for developers to implement form control validations, even for a novice developer with little knowledge on Javascript. However, it does lacks validators for some controls which are desperately needed for our day to day coding, say for instance CheckBox, CheckBoxList, etc. This article describes how to develop your own validator controls to validate any .net server controls with your own logics. Or broadly, how to extend a BaseValidator class with custom functionality?

Background
Required Field Validators are very popular among the .net validator controls. They works like a charm for Textbox, Dropdowns, FileUpload, etc. While writing any web form, say a feedback form or a registration form, we may have to use CheckBoxList controls to enable the user to ope multiple items from the list display. Here is the catch22. We dont have the validator...!. Instead, we should either write a lengthy code in javascript for client validation or use the Custom Validator Control to enable the validations in both the ends (server and client). User have another option to make use of partial rendering of pages for validation by using Ajax update panels control. However the later approach is troublesome and time consuming and is fully based on our host and network. Th built in validators are not allowed to be assigned for validation to any other controls like CheckBox since the ValidatedControlConverter will list only those webcontrols which can be validated. When creating your own validation control, you can enable the designer to display a list of controls that support validation controls.

Which Controls Can Be Validated?
In order to be referenced by a validation control, a control must have a validation property. All controls that can be validated have a ValidationPropertyAttribute, which indicates which property should be read for the purposes of validation. If you write your own control, you can make it take part in validation by providing one of these attributes to specify which property to use.

For validation to work client-side as well, this property must correspond to the value attribute of the HTML element that gets rendered on the client. Many complex controls such as DataGrid and Calendar do not have a value on the client and can only be validated on the server. This is why only controls that correspond closely to HTML elements can be involved in validation. Also, a control must have a single logical value on the client. This is why RadioButtonList can be validated, but CheckBoxList cannot

Knowledge Base - How to?
Every validators in .net is derived from the SuperClass BaseValidator. Hence it is the starting point. So while writing any validators for our use, we should derive our component from the BaseValidator to inherit all the default features of the validator controls.

public class RequiredFieldValidatorForCheckBoxList : BaseValidator
{
//..code..
}


Now, we have to override the boolean function below to implement our logic to validate the control to be validated.

protected override bool ControlPropertiesValid()
{
//check whether the ControlToValdate propery is set or not
if (this.ControlToValidate.Trim().Length == 0) return false;
Control ctrl = FindControl(ControlToValidate);
//check whether the right type of control is selected to validate
if ((ctrl == null)
(!(ctrl is <>)))
return false; else return true;
}


Next step is to implement the logic to validate or invalidate the control. This is done by overriding the boolean function EvaluateIsValid() (as shown below)

protected override bool EvaluateIsValid()
{
//code to implement the logic.
eg:- If the control is not checked, return true else return false.
}


Next step is implement the OnLoad event of the control to throw exception if either the control is not valid or control is not selected properly.

protected override void OnLoad(EventArgs e)
{
if (logic == false)
{
throw new HttpException(string.Format("ControlToValidate of {0}
is either blank or not a valid CheckBoxList control", this.ID)));
}
else if{second logic == false)
{
//throw another httpexception
}
}


Next is to enable listing of control in the design to be selected. Simply add an attribute to the string property that represents the control to validate, as follows:

[TypeConverter(typeof(ValidatedControlConverter))]
public string ControlToValidate
{
get
{
// Add code to get the ID of the control to validate.
//(should retrieve checkboxlists only)
}
set
{
// Add code to set the ID of the control to validate.
//(should set checkboxlists only)
}
}

Next and final step is to implement the javascript to enable the client side validation. To do that, you have to create a StringBuilder object and write the complete Javascript function to validate the control in the browser and implement it in OnPreRender function.


protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if((ControlPropertiesValid()) && (this.EnableClientScript))
InjectClientValidationScript();
if (this.ErrorMessage.Trim().Length == 0)
this.ErrorMessage = this.ID;
//default error message equal to the type of thecontrol
//if no error message specified while design time.
}



//code to generate clients javascript for validation
private void InjectClientValidationScript()
{
StringBuilder sb_Script = new StringBuilder();
sb_Script.Append("<script language="\""javascript\">");
sb_Script.Append("\r");
sb_Script.Append("\r");
sb_Script.Append("function validate_CBL(sender) {");
sb_Script.Append("\r");
sb_Script.Append("var val =
document.getElementById(document.getElementById
(sender.id).controltovalidate);");
sb_Script.Append("\r");
sb_Script.Append("var col =
val.getElementsByTagName(\"*\");");
sb_Script.Append("\r");
sb_Script.Append("if ( col != null ) {");
sb_Script.Append("\r");
sb_Script.Append("for ( i = 0; i < col.length; i++ ) {");
sb_Script.Append("\r");
sb_Script.Append
("if (col.item(i).tagName == \"INPUT\"){");
sb_Script.Append("\r");
sb_Script.Append("if ( col.item(i).checked ) {");
sb_Script.Append("\r");
sb_Script.Append("\r");
sb_Script.Append("return true;");
sb_Script.Append("\r");
sb_Script.Append("}");
sb_Script.Append("\r");
sb_Script.Append("}");
sb_Script.Append("\r");
sb_Script.Append("}");
sb_Script.Append("\r");
sb_Script.Append("\r");
sb_Script.Append("\r");
sb_Script.Append("return false;");
sb_Script.Append("\r");
sb_Script.Append("}");
sb_Script.Append("\r");
sb_Script.Append("}");
sb_Script.Append("\r");
sb_Script.Append("</script>");
//Inject the script into the page
Page.ClientScript.RegisterClientScriptBlock
(GetType(), "SCRIPTBLOCK", sb_Script.ToString());
//Registering validator clientside javascript function
Page.ClientScript.RegisterExpandoAttribute
(ClientID, "evaluationfunction", "validate_CBL");

}



Since we have derived our component from the BaseValidator class, our new control woul inherit all the default behaviour of the parent with zero effort. Care shoul only be taken to implement our logic to make it work. I have developed a control (ready to use) to validate CheckBoxList control. The control would exactly similiar way as other required field validator controls from Microsoft. It has a built in functionality to specify how many checkboxes to be ticked for a successfull validation. It is having a default value of 1 saying only one checkbox tick will successfully validate the control where as Zero represent all the items in the list is to be ticked for successfull validation.

Download
You can download the latest release of fully functional control from http://code.msdn.microsoft.com/ZNetControls

Tested Platforms : IE and FireFox browsers.


-::-

16 comments:

Anonymous said...

this is very nice blog...
visit for asp.net help asp.net help

Unknown said...

Nice control. I had 1 issue, I have a list of checkboxes and the user is only required to check 1 but could check all of them if they wish. If the user selects more than one, it displays the error message. I tried using the NumberOfCheckBoxesToBeChecked property but that seems to do the same thing (but will require the user to check the number indicated). Thanks for the control!

Bob said...

I have the same issue about more than 1 box being checked. Works great if you just want to check if 1 checkbox is checked. But then I would use a radio button control instead.

There are many cases where you need a checkboxlist control and want to set the control to have a certain number to be select. "Please select your top 3 reasons for......".

The control could have a setting, "MinimumCheckBoxesToBeChecked" and a "MaximumCheckBoxesToBeChecked".

But thanks for great article!

Mark said...

Great control, however the most common validation requirement for a group of checkboxes is to validate that at least one checkbox was selected. How do I do this with this control the NumberOfCheckBoxesToBeChecked property appears to require an exact match to the value entered not min number of boxes required.
Thanks Mark

medoyoga2 said...

I would like to use your control, however the "Download" link http://code.msdn.microsoft.com/ZNetControls seems to be broken. How can I get the control?

medoyoga2 said...

I would like to use your control, however the "Download" link http://code.msdn.microsoft.com/ZNetControls seems to be broken. How can I get the control

dotNetSoldier said...

The link is not broken. Please try again.

dotNetSoldier said...

Mark,

The validation, "minimum no. of checkboxes to be validated" is not available in the current version. However, i am working on that and you can expect it in the next version. The buys schedules are not allowing me to spend time on this.

dotNetSoldier said...

Bob,
You may get this validation in the next version of the control

Anonymous said...

I followed links from MSDN to get here, I haven't followed any instructions on how to actually use the .dll file that was the download.

Also, when will the next version be released? Surely the Min/Max checkboxes checked is a biggie! Go on.. release a new one!

Any help appreciated

dotNetSoldier said...

I have completed 40 to 50% of the work of the component for next release. Unfortunately, i am completely tied up with all sorts of projects..You can expect it soon

Rob Joosen said...

very nice but.....

When I enable this control server-side at runtime, it doesn't work.

I want to have this validator to check only when the user has selected something in a dropdown. So in Page Load(!postsback) I set enabled = false, and in SelectedIndex_Changed event I set enabled to true. Too bad, it doesn't do the validation.

Unknown said...

How does the ShowGroupItemCount property work? All the time when I choose "true", I got "specified argument was out of the range of valid values. Parameter name: index".

Thanks for that control. It's great

Unknown said...

awesome control. any chance of getting it to accept "select as many as you need to, but at least 1" situation? This control does it, but does not write to summary control : http://codeclimber.net.nz/archive/2007/07/19/How-to-add-a-required-validator-to-a-CheckBoxList.aspx
I'd update it myself but dont understand summary control well enough.

thanks

Kalaivanan said...

This is nice, I had one issue,
My page have one checkboxlist control and one dropdown control(dropdown is a autopostback), if i made any selection in dropdown that time checkboxlist validator is not working. how to solve this?

Memtech said...

Hi,

This is very informative article. Thanks for sharing your knowledge. There are few links that also helpful for developers. This article have described to validate CheckBox, CheckBoxList, DropDownList, FileUpload, RadioButton, RadioButtonList, TextBox using jquery.

http://mindstick.com/Articles/c3825daa-a449-467d-9513-34a8232d498a/?Validations%20on%20Asp%20Net%20Control
http://www.aspdotnet-suresh.com/2012/09/jquery-validate-checkboxlist-in-aspnet.html