This class library consists of two class files, the CBLValidator class and the ControlConverter Class. The ControlConverter Class inherits from the StringConverter Class, which allows us to pass the name of the control to validate as a string and convert it to a Control object.
This class consists of two methods, both of which are marked with the override modifier, which allows us to override this base method to fit our needs. The first method is the GetStandardValuesSupported(ITypeDescriptorContext). We override this method to simply return true.
As with any class we create in .Net we need to make sure we have a reference to the proper Namespaces, for this class we use
using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Collections;
Now lets take a look at the two methods in this class
/// <summary> /// Checks the page context to see if standard values are supported. /// </summary> /// <param name="context">The web page's context object.</param> /// <returns>A boolean true/false value.</returns> /// <remarks></remarks> public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; }
The 2nd method is the GetStandardValues(ITypeDescriptorContext) Method, which we override to gather all the items in the CheckBoxList Control we are validating and add them to an ArrayList
/// <summary> /// Parses the page context and finds all CheckBoxList IDs. /// </summary> /// <param name="context">The web page's context object.</param> /// <returns>A StandardValuesCollection of CheckBoxList IDs.</returns> /// <remarks></remarks> public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { ArrayList cblArray = new ArrayList(); foreach (Control control in context.Container.Components) { try { if (object.ReferenceEquals(control.GetType(), typeof(CheckBoxList))) { if (control.ID.StartsWith("_ctl")) { cblArray.Add(control.ID.Remove(1, control.ID.ToString().IndexOf('_', 1) + 1)); } else { cblArray.Add(control.ID); } } } catch (Exception ex) { throw ex; } } return new StandardValuesCollection(cblArray); }
We use this class when we set the ControlToValidate Property of our CBLValidator control, so now lets take a look at that class. As with any class we need to ensure we have a reference to the proper Namespaces, in this class we use the following Namespaces:
using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls;
Properties
Our validation control consists of five Properties:
- MinRequired: Minimum number of items that are required to be selected in the control being validated
- MaxAllowed: Maximum number of items that can be selected in the control being validated (Set to zero to allow all items to be selected)
- ControlPropertiesValid: Determines if the control specified in the ControlToValidate property is a valid control
- ControlToValidate: The control we are validating.
So lets take a look at these properties:
MinRequired:
/// <summary> /// The minimum number of checkboxes allowed to be checked. /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> [System.ComponentModel.Description("The minimum number of checkboxes allowed to be checked.")] public Int32 MinRequired { get { try { int num = 0; if (Int32.TryParse(ViewState["MinimumCheckBoxesRequired"].ToString(), out num)) { return num; } else { return 1; } } catch (Exception ex) { throw new Exception(ex.Message); } } set { try { ViewState["MinRequired"] = value; } catch (Exception ex) { throw new Exception(ex.Message); } } }
MaxAllowed
/// <summary> /// The maximum number of checkboxes allowed to be checked. Set this to zero to allow all. /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> [System.ComponentModel.Description("The maximum number of checkboxes allowed to be checked. Set this to zero to allow all.")] public Int32 MaxAllowed { get { try { Int32 num = 0; Int32.TryParse(ViewState["MaxAllowed"].ToString(), out num); return num; } catch (Exception ex) { throw new Exception(ex.Message); } } set { try { ViewState["MaximumCheckBoxesAllowed"] = value; } catch (Exception ex) { throw new Exception(ex.Message); } } }
ControlToValidate
/// <summary> /// Gets or sets the CheckBoxList to validate. /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> [System.ComponentModel.Description("Gets or sets the CheckBoxList to validate."), System.ComponentModel.TypeConverter(typeof(ControlConverter))] public new string ControlToValidate { get { try { object control = ViewState["ControlToValidate"]; if (control == null) { return string.Empty; } else { return control.ToString(); } } catch (Exception ex) { throw new Exception(ex.Message); } } set { try { ViewState["ControlToValidate"] = value; } catch (Exception ex) { throw new Exception(ex.Message); } } }
ControlPropertiesValid
protected override bool ControlPropertiesValid() { try { return true; } catch (Exception ex) { throw new Exception(ex.Message); } }
Methods
Our control consists of four (4) methods:
- EvaluateIsValid: Method to determine if validation was successful
- EvaluateIsChecked: Method to determine is the proper number of items are selected
- OnPreRender: Method that adds our client-side validation code to the control before it is rendered
- BuildValidation: This is the method that creates our client-side validation code
Now lets take a look at each of these methods:
EvaluateIsValid
/// <summary> /// method to determine if the validation failed or succeeded /// </summary> /// <returns></returns> protected override bool EvaluateIsValid() { try { return EvaluateIsChecked(); } catch (Exception ex) { throw new Exception(ex.Message); } }
EvaluateIsChecked
/// <summary> /// Server side code to check that the required number of checkboxes are checked. /// </summary> /// <returns>A boolean value </returns> /// <remarks></remarks> protected bool EvaluateIsChecked() { try { //get the control to validate CheckBoxList list = null; list = (CheckBoxList)this.FindControl(this.ControlToValidate); //initialize items checked to zero Int32 count = 0; //count each selected item foreach (ListItem item in list.Items) { if (item.Selected) { count += 1; } } //make sure it falls within MinRequired and MaxAllowed if (count >= MinRequired & (count <= MaxAllowed | MaxAllowed == 0)) { //if it's in the range return true return true; } //otherwise return false return false; } catch (Exception ex) { throw new Exception(ex.Message); } }
OnPreRender
/// <summary> ///adds our client-side validation code to the control /// </summary> /// <param name="e"></param> /// <remarks> ///checks first to make sure the control has EnableClientScript enabled ///</remarks> protected override void OnPreRender(EventArgs e) { try { //check and see if client script is enabled for the control if (EnableClientScript) { //build our validation script BuildValidation(); } //pre-render the control base.OnPreRender(e); } catch (Exception ex) { throw new Exception(ex.Message); } }
BuildValidation
/// <summary> /// method for building the validation code for the ChecKBoxList control /// we wish to validate /// </summary> /// <remarks></remarks> protected void BuildValidation() { try { ClientScriptManager manager = this.Page.ClientScript; Type type = this.GetType(); if (!(manager.IsClientScriptBlockRegistered(type, "StartVerification" + this.ClientID))) { this.Attributes.Add("evaluationfunction", "start_verification_" + this.ClientID); StringBuilder builder = new StringBuilder(); builder.Append("<script language=\"javascript\">" + Environment.NewLine); builder.Append("<!--" + Environment.NewLine); builder.Append("function start_verification_" + this.ClientID + "(val) {" + Environment.NewLine); builder.AppendFormat("\t"); builder.Append("return checkboxlist_verification('" + this.ClientID + "');" + Environment.NewLine); builder.Append("}" + Environment.NewLine); builder.Append("-->" + Environment.NewLine); builder.Append("</script>" + Environment.NewLine); if (ScriptManager.GetCurrent(this.Page) == null) { manager.RegisterClientScriptBlock(type, "StartVerification" + this.ClientID, builder.ToString()); } else { ScriptManager.RegisterClientScriptBlock(this.Page, typeof(Page), "StartVerification" + this.ClientID, builder.ToString(), false); } } if (!(manager.IsClientScriptBlockRegistered(type, "CheckBoxListVerification" + this.ClientID))) { StringBuilder builder = new StringBuilder(); builder.Append("<script language=\"javascript\">" + Environment.NewLine); builder.Append("<!--" + Environment.NewLine); builder.Append("function checkboxlist_verification(clientID) {" + Environment.NewLine); builder.AppendFormat("\t"); builder.Append("var val = document.all[document.all[clientID].controltovalidate];" + Environment.NewLine); builder.AppendFormat("\t"); builder.Append( "var col = val.all;" + Environment.NewLine); builder.AppendFormat("\t"); builder.Append("if (col != null ) {" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("var checked = 0;" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("var checkboxcount = 0;" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("for (i = 0; i < col.length; i++ ) {" + Environment.NewLine); builder.AppendFormat("\t\t\t"); builder.Append("if (col.item(i).tagName == 'INPUT') {" + Environment.NewLine); builder.AppendFormat("\t\t\t\t"); builder.Append("checkboxcount += 1;" + Environment.NewLine); builder.AppendFormat("\t\t\t\t"); builder.Append("if (col.item(i).checked ) {" + Environment.NewLine); builder.AppendFormat("\t\t\t\t\t"); builder.Append("checked += 1;" + Environment.NewLine); builder.AppendFormat("\t\t\t\t"); builder.Append("}" + Environment.NewLine); builder.AppendFormat("\t\t\t"); builder.Append("}" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("}" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("if (checked >= " + MinRequired + " && (checked <= " + MaxAllowed + " || " + MaxAllowed + " == 0))" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("{" + Environment.NewLine); builder.AppendFormat("\t\t\t"); builder.Append("DOMCall(cbxAll).checked = false;" + Environment.NewLine); builder.AppendFormat("\t\t\t"); builder.Append("return true;" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("}" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("else {" + Environment.NewLine); builder.AppendFormat("\t\t\t"); builder.Append("return false;" + Environment.NewLine); builder.AppendFormat("\t\t"); builder.Append("}" + Environment.NewLine); builder.AppendFormat("\t"); builder.Append("}" + Environment.NewLine); builder.Append("}" + Environment.NewLine); builder.Append("-->" + Environment.NewLine); builder.Append("</script>" + Environment.NewLine); if (ScriptManager.GetCurrent(this.Page) == null) { manager.RegisterClientScriptBlock(type, "CheckBoxListVerification" + this.ClientID, builder.ToString()); } else { ScriptManager.RegisterClientScriptBlock(this.Page, typeof(Page), "CheckBoxListVerification" + this.ClientID, builder.ToString(), false); } } } catch (Exception ex) { throw new Exception(ex.Message); } }
You will notice that the bulk of the work is done in the BuildValidation method, this is where the code for validating the control is created.
Well there you have it, a custom control to validate a CheckBoxList Control. I have, since creating it, found this control to be an invaluable addition to my code library, and I use it often. I hope you have found this tutorial useful and informative. Next I will port this same control for a Windows application and create a tutorial for it as well. Thanks for reading.
Happy Coding!