Part 2 - Part 1 - Building a Custom Validator Control
As promised, this week we will be going over how to add client-side JavaScript to a custom validator control. But
last week I was asked a very interesting question. What validator control should I use to validate that a CheckBox was
checked within a CheckBoxList? The anwser was simple, NONE. None of the validator controls in the .NET valiator control
suite does this type of validation. So, in this article not only are we going to discuss how to add JavaScript validation
control for client-side validation, but how to create a CheckBoxListRequiredFieldValidator control. Wow, now that
is one hell of a long name, excuse my english! So let's get to it! In the first part of this article I'll go over some
of the problems I ran into building this control and how I solved them. Then we'll look at the source code and finally
the implementation code.
|
Creating the CheckBoxListRequiredFieldValidator required a little object manipulation and trickery. Mainly because the
CheckBoxList control is not a control that is supported by any of the typical validation control and hence if you try to
set any of their ControlToValidate properties to a CheckBoxList an exception would be thrown. Documentation on this subject is nill so I began
to experiment. I found that if I override the ControlPropertiesValid base property and return true I could validate any server control I wanted.
The second tricky part was figuring out how client-side validation was done, but this was easily figured out by
walking through the WebUIValidation.js and looking at how typical validation controls do it. Well, I always find that looking at code is a lot easier than
reading about it so let's look at the code.
|
|
RadioButtonListRequiredFieldValidator.cs
|
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Validators {
public class RadioButtonListRequiredFieldValidator : BaseValidator {
protected override bool ControlPropertiesValid(){
return true;
}
protected override bool EvaluateIsValid() {
return this.EvaluateIsChecked();
}
protected bool EvaluateIsChecked() {
CheckBoxList _cbl = ( ( CheckBoxList ) this.FindControl( this . ControlToValidate ) );
foreach( ListItem li in _cbl.Items ) {
if ( li.Selected == true ) {
return true;
}
}
return false;
}
protected override void OnPreRender( EventArgs e ){
if ( this.EnableClientScript ) { this.ClientScript(); }
base.OnPreRender( e );
}
protected void ClientScript() {
this.Attributes["evaluationfunction"] = "cb_vefify";
StringBuilder sb_Script = new StringBuilder();
sb_Script.Append( "<script language=\"javascript\">" );
sb_Script.Append( "\r" );
sb_Script.Append( "\r" );
sb_Script.Append( "function cb_vefify(val) {" );
sb_Script.Append( "\r" );
sb_Script.Append( "var val = document.all[document.all[\"" );
sb_Script.Append( this.ID );
sb_Script.Append( "\"].controltovalidate];" );
sb_Script.Append( "\r" );
sb_Script.Append( "var col = val.all;" );
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>" );
this.Page.RegisterClientScriptBlock( "RBLScript", sb_Script.ToString() );
}
}
}
|
|
Compile Code - Make.Bat
|
csc.exe /target:library /out:../../bin/RadioButtonListRequiredFieldValidator.dll *.cs /r:System.dll,System.Web.dll
pause
|
|
Note: Make sure to copy the assembly into your application /bin directory to use.
|
|
Web Form - TestValidator.aspx
|
<%@ Register TagPrefix="DNJValidators" Namespace="Validators" Assembly="RadioButtonListRequiredFieldValidator" %>
<%@ import namespace="System.Data.SqlClient" %>
<script language="C#" runat="Server">
protected void Page_Load( object sender, EventArgs e ){
if ( ! IsPostBack ) this.BindCBL();
}
protected void BindCBL(){
SqlConnection SqlCon = new SqlConnection( "server=localhost;database=northwind;trusted_connection=true" );
SqlCommand SqlCmd = new SqlCommand( "SELECT TOP 10 ProductName, ProductID FROM Products", SqlCon );
SqlCon.Open();
cb.DataSource = SqlCmd.ExecuteReader();
cb.DataTextField = "ProductName";
cb.DataValueField = "ProductID";
cb.DataBind();
}
</script>
<html>
<body>
<form runat="server">
<H3>RadioButtonList Validator</H3>
<!-- Summary -->
<asp:ValidationSummary
id="valSum"
DisplayMode="BulletList"
runat="server"
HeaderText="You must enter a value in the following fields:"
Font-Name="verdana"
Font-Size="8" />
<BR>
<!-- Summary -->
<P>
<!-- Our Validator -->
<B>You must select one item</B>
<DNJValidators:RadioButtonListRequiredFieldValidator
ID="valMessage"
ControlToValidate="cb"
RUNAT="SERVER"
EnableClientScript="true"
ErrorMessage="You must check at least one check box">
*
</DNJValidators:RadioButtonListRequiredFieldValidator>
<BR>
<asp:CheckBoxList runat="server" id="cb" />
<!-- Our Validator -->
<P>
<!-- Intrinsic Validator -->
<B>You must fill out</B>
<asp:RequiredFieldValidator
id="RF"
runat="server"
ControlToValidate="txt"
ErrorMessage="You must fill out text box">
*
</asp:RequiredFieldValidator>
<BR>
<asp:TextBox id="txt" runat="server" />
<!-- Intrinsic Validator -->
<p>
<asp:Button id="submit" Text="Submit" runat="server" />
</form>
</body>
</html>
|
You have probably noticed three new things in this server control when compared to the last. The first is the ControlPropertiesValid we
discussed earlier. Second, is the OnPreRender event and third is the ClientScript method. The following table contains a description of each.
| ControlPropertiesValid |
OnPreRender |
ClientScript |
| This is a helper function that determines if the control specified by the ControlToValidate property is a valid control. It should return true if it is otherwise false. |
This method not only raises the PreRender event, but also invokes the RegisterValidatorCommonScript method which registers code for client
side validation. I use the OnPreRender method to invoke the ClientScript method which registers our client side script after which I invoke the base.OnPreRender method which invokes the BaseValidator.OnPreRender method. I do this so the regular validation script is also rendered so we can take advantage of it |
This method registers our client side validation script. |
|
|
So let's try it out, the following image illustrates TestValidator.aspx after an attempt to submit the page has been made
with no checkboxes checked and nothing entered into the textbox. Following that image is the page after just one checkbox
has been checked
|
|
|
|
If you have any specific requests for a server control example (one that will not take over 1000 lines of code) please don't hesitate to email me at Tell Donny Mack What's Up!!!!
|
|
|
|