3.6 使用CustomValidator控件
如果各种验证控件执行的验证类型都不是你所需的,那么还可以使用CustomValidator控件。可以为CustomValidator控件关联一个验证函数。
CustomValidator控件有3个重要的属性:
q ControlToValidate——验证的表单字段的ID。
q Text——验证失败显示的错误信息。
q ClientValidationFunction——用于执行客户端验证的客户端函数名。
CustomValidator还支持一个事件:
q ServerValidate——CustomValidator执行验证时引发。
可以通过处理ServerValidate事件来将自定义验证函数和CustomValidator控件相关联。
例如,假设想验证输入表单字段的字符串的长度,要确认用户没有向一个多行的TextBox控件中输入超过10个的字符。代码清单3-14中的页面包含一个CustomValidator控件的ServerValidate事件的事件处理程序,用于检查字符串长度。
代码清单3-14 ShowCustomValidator.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void valComments_ServerValidate(Object source, ServerValidateEventArgs args)
{
if (args.Value.Length > 10)
args.IsValid = false;
else
args.IsValid = true;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Show CustomValidator</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label
id="lblComments"
Text="Comments:"
AssociatedControlID="txtComments"
Runat="server" />
<br />
<asp:TextBox
id="txtComments"
TextMode="MultiLine"
Columns="30"
Rows="5"
Runat="server" />
<asp:CustomValidator
id="valComments"
ControlToValidate="txtComments"
Text="(Comments must be less than 10 characters)"
OnServerValidate="valComments_ServerValidate"
Runat="server" />
<br /><br />
<asp:Button
id="btnSubmit"
Text="Submit"
Runat="server" />
</div>
</form>
</body>
</html>
传给ServerValidate事件处理程序的第二个参数是ServerValidateEventArgs类的一个实例。该类有3个属性:
q Value——表示被验证的表单字段的值。
q IsValid——表示验证成功或失败。
q ValidateEmptyText——表示所验证的表单字段没有值时是否执行验证。
代码清单3-14中,Value属性所表示的字符串如果长于10个字符,就会为IsValid属性赋值False,并且验证失败。反之,为IsValid属性赋值True,并且输入字段通过验证检测(见图3-12)。
代码清单3-14中的ServerValidate处理程序是服务器端函数。因此,页面传回Web服务器端后才会引发验证。如果想要在客户端(浏览器)和服务器端都执行验证,那么就需要客户端验证函数。
注解 如果不为CustomValidator控件关联一个客户端验证函数,那么要到页面回传到服务器端后,CustomValidator控件才会呈现错误信息。此外,如果有任何的验证错误,其他的验证控件都将阻止页面表单回传,所以需通过页面中其他验证检查后,才能看到CustomValidator控件呈现的错误信息。
代码清单3-15中的页面展示如何把客户端验证函数和CusomValidator控件关联起来。该页面也检查输入TextBox控件的字符串长度,但是,它在客户端和服务器端都进行检查。

图3-12 用CustomValidator控件检查字段长度
代码清单3-15 ShowCustomValidatorJS.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void valComments_ServerValidate(Object source, ServerValidateEventArgs args)
{
if (args.Value.Length > 10)
args.IsValid = false;
else
args.IsValid = true;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<script type="text/javascript">
function valComments_ClientValidate(source, args)
{
if (args.Value.length > 10)
args.IsValid = false;
else
args.IsValid = true;
}
</script>
<title>Show CustomValidator with JavaScript</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label
id="lblComments"
Text="Comments:"
AssociatedControlID="txtComments"
Runat="server" />
<br />
<asp:TextBox
id="txtComments"
TextMode="MultiLine"
Columns="30"
Rows="5"
Runat="server" />
<asp:CustomValidator
id="valComments"
ControlToValidate="txtComments"
Text="(Comments must be less than 10 characters)"
OnServerValidate="valComments_ServerValidate"
ClientValidationFunction="valComments_ClientValidate"
Runat="server" />
<br /><br />
<asp:Button
id="btnSubmit"
Text="Submit"
Runat="server" />
</div>
</form>
</body>
</html>
注意代码清单3-15页面中的CustomValidator控件含有ClientValidationFunction属性。该属性包含定义在页面<head>标签中的JavaScript函数名。
像服务器端验证函数一样,该JavaScript函数同样接受两个参数。第一个参数代表CustomValidator控件,第二个参数代表一个包含Value和IsValid属性的对象。这个客户端函数几乎和服务器端函数一样(最大的不同是用JavaScript编写)。
跟RangeValidator、CompareValidator和RegularExpressionValidator这些控件不同,可以使用CustomValidator控件来验证表单字段,就算表单字段为空。CustomValidator控件有一个属性,名为ValidateEmptyText。这个属性用来使CustomValidator控件即使用户没有输入值也验证表单字段。例如,代码清单3-16中的页面包含一个TextBox,要求输入严格限制为4个字符的产品代码。
代码清单3-16 ShowValidateEmptyText.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void valProductCode_ServerValidate(Object source, ServerValidateEventArgs args)
{
if (args.Value.Length == 4)
args.IsValid = true;
else
args.IsValid = false;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Show Validate Empty Text</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label
id="lblProductCode"
Text="Product Code:"
AssociatedControlID="txtProductCode"
Runat="server" />
<br />
<asp:TextBox
id="txtProductCode"
Runat="server" />
<asp:CustomValidator
id="valProductCode"
ControlToValidate="txtProductCode"
Text="(Invalid product code)"
ValidateEmptyText="true"
OnServerValidate="valProductCode_ServerValidate"
Runat="server" />
<br /><br />
<asp:Button
id="btnSubmit"
Text="Submit"
Runat="server" />
</div>
</form>
</body>
</html>
注意,代码清单3-16中的CustomValidator控件包含一个值为True的ValidateEmptyText属性。如果没有ValidateEmptyText属性,不输入任何数据就提交表单,也不会显示验证错误信息。
最后,不同于其他验证控件,不一定要把CustomValidator控件和表单字段关联。换句话说,ControlToValidate属性不是必须的。
例如,代码清单3-17中的页面含有一个定时测试。如果五分钟内没有回答问题,CustomValidator控件就显示一个验证错误信息(见图3-13)。

图3-13 执行不针对特定字段的验证
代码清单3-17 TimedTest.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Page_Load()
{
if (!Page.IsPostBack)
ResetStartTime();
}
void btnAgain_Click(Object sender, EventArgs e)
{
ResetStartTime();
}
void ResetStartTime()
{
Session["StartTime"] = DateTime.Now;
}
void valAnswer_ServerValidate(Object source, ServerValidateEventArgs args)
{
DateTime startTime = (DateTime)Session["StartTime"];
if (startTime.AddSeconds(5) > DateTime.Now)
args.IsValid = true;
else
args.IsValid = false;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Timed Test</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
You have 5 seconds to answer the following question:
</p>
<asp:Label
id="lblQuestion"
Text="What was Aristotle's first name?"
AssociatedControlID="txtAnswer"
Runat="server" />
<br />
<asp:TextBox
id="txtAnswer"
Runat="server" />
<asp:CustomValidator
id="valAnswer"
Text="(You answered too slowly!)"
OnServerValidate="valAnswer_ServerValidate"
Runat="server" />
<br /><br />
<asp:Button
id="btnSubmit"
Text="Submit"
Runat="server" />
<asp:Button
id="btnAgain"
Text="Try Again!"
CausesValidation="false"
OnClick="btnAgain_Click"
Runat="server" />
</div>
</form>
</body>
</html>






