一 、實現的效果
我想對於ASP.Net的Validator控件已經熟悉的不能再熟悉了。我們 已經習慣了用Validator控件來驗證我們在表單的輸入,並通過ValidationSummary來輸出我們為Validator控件設置的Error message。不知道大家有沒想過進一步改進一下我們的Validation來改善我們的User ExperIEnce。比如,在ValidationSummary輸出一個Link連接到對應的控件,而不是顯示單純的Error message。
比如在上圖中,是一個典型的Login的Page。我們有兩個必填的字段:User name和Password。為此我定義兩個RequiredFIEldValidator。他們的Error message分別為:”User name is mandatory!”和”PassWord is mandatory!”。在未輸入任何值得前提下Click “Sign in”按鈕,Error Message被顯示在ValidationSummary上面。不過和傳統的Error message不同,顯示在ValidationSummary上的實際上是兩個鏈接,Click對應的Error message,光標會設置到對應的Textbox上。比如上圖所示:Click ”User name is mandatory!”,光標回到User name對應的Texbox。
二、具體實現
現在我們來簡單敘述上面的效果是如果實現的,在開始之前我想說的是,方法非常簡單—或許你已經猜到了:)
1.首先來看看ASPx。
<%
@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.ASPx.cs" Inherits="Login" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xHtml1-transitional.dtd">
<html XMLns="http://www.w3.org/1999/xHtml">
<head id="Head1" runat="server">
<title>Login</title>
<style type="text/CSS">
body{
}{font-family:Verdana; font-size:10px}
table{
}{width:300px}
table tr{
}{height:30px}
table td.firstColumn{
}{width:100px; text-align:right}
table td.secondColumn{
}{ text-align:left}
table span.asterisk{
}{color:red}
table .textbox{
}{width:150px; border:solid 1px #999999}
table .button{
}{background-color: #00cc66;border:solid 1px #999999}
ul li{
}{margin-bottom:5px}
ul li a{
}{color:red; text-decoration:none}
ul li a:hover{
}{text-decoration:underline}
</style>
<script type="text/Javascript">
function setFocus(control)
{
var controlToValidate = document.getElementById(control);
controlToValidate.focus();
}
</script>
</head>
<body >
<form id="form1" runat="server">
<div>
<table cellpadding="0" cellspacing="5px">
<tr>
<td colspan="2">
<ASP:ValidationSummary runat="server" ID="vldLogin" />
</td>
</tr>
<tr>
<td class="firstColumn">
User Name: <span class="asterisk"> *</span></td>
<td class="secondColumn">
<asp:TextBox runat="server" ID="txtUserName" CSSClass="textbox"></ASP:TextBox>
<asp:RequiredFIEldValidator runat="server" ID="rqfUserName" ControlToValidate="txtUserName" Display="None"></ASP:RequiredFIEldValidator>
<asp:CustomValidator runat="server" ID="ctmUserName" Display="None" OnServerValidate="ctmUserName_ServerValidate" ControlToValidate="txtUserName" ></ASP:CustomValidator>
</td>
</tr>
<tr>
<td class="firstColumn">
PassWord: <span class="asterisk"> *</span></td>
<td class="secondColumn">
<asp:TextBox runat="server" ID="txtPassword" TextMode="PassWord" CSSClass="textbox"></ASP:TextBox>
<asp:RequiredFIEldValidator runat="server" ID="rqfPassword" ControlToValidate="txtPassWord" Display="None" ></ASP:RequiredFIEldValidator>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<ASP:Button runat="server" ID="btnSignIn" Text="Sign in" CSSClass="button" />
<ASP:Button runat="server" ID="ButtonCancel" Text="Cancel" CausesValidation="false"
CSSClass="button" />
</td>
</tr>
</table>
</div>
</form>
</body>
</Html>
在看到了上面的Screen shot之後再看看上面的Html,結構清晰得一目了然。所以我就不再進一步解釋了。在這裡我只需要提提定義在ASPx的一段Javascript function:setFocus。通過它把focus設置到指定的控件。
<script type="text/Javascript">
function setFocus(control)
{
var controlToValidate = document.getElementById(control);
controlToValidate.focus();
}
</script>
2.接著我們來看看code behind。
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
{
return;
}
this.rqfUserName.ErrorMessage = string.Format("{0} is mandatory!", "User name");
this.rqfPassword.ErrorMessage = string.Format("{0} is mandatory!", "PassWord");
this.ctmUserName.ErrorMessage = "Such a user has not registered!";
this.MakeClickableErrorMessage();
}
private void MakeClickableErrorMessage()
{
foreach (BaseValidator validator in this.Validators)
{
if (validator.ControlToValidate == string.Empty)
{
continue;
}
string clientID = this.FindControl(validator.ControlToValidate).ClIEntID;
string script = string.Format("<a href= \"Javascript:setFocus(''{0}'');\">{1}</a>", clIEntID, validator.ErrorMessage);
validator.ErrorMessage = script;
}
}
protected void ctmUserName_ServerValidate(object source, ServerValidateEventArgs args)
{
if (this.txtUserName.Text.Trim() != "adm")
{
args.IsValid = false;
return;
}
args.IsValid = true;
}
}
Code也簡單得一塌糊塗,除了MakeClickableErrorMessage這個Method,其他的都不值一提。
private void MakeClickableErrorMessage()
{
foreach (BaseValidator validator in this.Validators)
{
if (validator.ControlToValidate == string.Empty)
{
continue;
}
string clientID = this.FindControl(validator.ControlToValidate).ClIEntID;
string script = string.Format("<a href= \"Javascript:setFocus(''{0}'');\">{1}</a>", clIEntID, validator.ErrorMessage);
validator.ErrorMessage = script;
}
}
顯示在ValidationSummary中原本簡單的literal error message就是通過上面的這個MakeClickableErrorMessage轉變成hyperlink的。在上面的code中,我遍歷page中的每個Validator control。如果該Validator control有對應ControlToValidate(對於一個Validator control來說,ControlToValidate並非一個必需的property,如果沒有指定該property,其值為空字符串),直接進入下一個循環。然後我把原來只是彈出的文本轉變成一個<a></a>,然後再將其重新賦值給對應的Validator contorl的ErrorMessage property。