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.


-::-

Monday, August 4, 2008

Extended GridView for Asp.Net 2.0 with Custom Grouping and Record Indexing

Grouping in GridView

When we start writing apps in asp.net, we always get hold off if we miss some functionality that we desperately need to roll out the solution. And the case is true always when we write code with Asp.Net's GridView control... When i started with one of the developments (Web Portal), i was running into issues since i dont have those expected functionalities available in the classic asp.net 2.0 controls. I was being asked by the business owners to have grouping in the listing while display data. The only option left off is to go for third party components like infragistics and i have to shed dollars from my pocket to have it done. Having said that, i started thinking.. "Why can't i have a simple control extended from the classic to have those required functionalites instead buying..?". There i started..And i became successfull in delivering the solution .Now the control is complete and i have few more ideas to be incorporated within the control, but in future. The control is free to use and distribute with no restrictions and royality. The current version has only GridView with grouping functionality based on DataKeys and record indexing, all with CSS styles....

How to use the control?



  1. Download the control from the link below

  2. Add the control to your ToolBox panel by locating the dll file.

  3. Drag ZNetGridView on your .aspx form

  4. Define the properties of the control

















  5. For grouping, make EnableGrouping = true and set the CSS for Grouping header inside the "Grouping" cateogry of properties window. To make grouping inside the control, you have to first specify the datakey(s) for data binding and then specify the "GroupingDataKeyIndex" for grouping so that the control will group with respect to that particular datakey. Care should be taken that the GroupingDataKeyIndex should always be less than count of datakey(s)

  6. User has the option to make the header visible inside each group (multi header gridview) as below.













    To enable it, make "ShowColumnHeaderInsideGroups" = true

  7. For record indexing, make "EnableRecordIndexing" = true in the "Record Indexing" cateogory of property dialog box. You can set the header text for indexing column and CSS styles as well




Download
The latest release of the control is available for downlad at http://code.msdn.microsoft.com/ZNetControls

Tested Platforms : IE and FireFox browsers.