最近在一个项目中 ,需要填写行政区划,为了防止用户填写错误,应该用下拉选择来代替文本输入,但全国的行政区划有3000多个,用下拉来选择是不现实的,最后决定用文本框,但采用自动完成来避免用户输入错误。这里我用一个产品名称填写来说明,如下图所示:
实现方式是采用ASP.Net的客户端回调实现的,具体的实现方式包括:
- 实现ICallbackEventHandler,这个接口可以指定任何页面实现,其中包括实现一个 RaiseCallbackEvent方法,它向客户端回调的函数返回一个字符串
此外,该页还必须包含执行以下操作的三个客户端脚本函数:
-
一个函数调用帮助器方法,该方法执行对服务器的实际请求。在此函数中,可以首先执行自定义逻辑以准备事件参数,然后可以将一个字符串作为参数发送到服务器端回调事件处理程序。
-
另一个函数由处理回调事件的服务器代码的结果调用并接收该结果,同时接受表示该结果的字符串。该函数称为 clientCallBack 函数。
-
第三个函数是执行对服务器的实际请求的 Helper 函数,当在服务器代码中使用 GetCallbackEventReference 方法生成对此函数的引用时,由 ASP.NET 自动生成该函数。
客户每次在文本框中按下键盘,系统都执行客户端脚本,客户端脚本中调用客户端回调函数,客户端回调函数向服务器端发起回调,触发RaiseCallbackEvent,最后由GetCallbackResult把得到的数据发送回客户端,客户端接收函数接收数据并处理。
以下是代码:
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;
using System.Collections.Generic;
public partial class _Default : System.Web.UI.Page, ICallbackEventHandler
{
IList<Product> list = null;
protected void Page_Load(object sender, EventArgs e)
{
// 注册客户端回调
RegisterClientCallbacks();
}
private void RegisterClientCallbacks()
{
string callbackRef = ClientScript.GetCallbackEventReference(this, "arg", "RecieveServerData", "context");
string script = String.Empty;
if (!ClientScript.IsClientScriptBlockRegistered("CallServer"))
{
script = "function CallServer(arg,context) { " + callbackRef + "}";
ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer", script, true);
}
}
public string GetCallbackResult()
{
return HtmlTableHelper.ConvertProductListToTable(list); //把Product列表专程一段Html代码,可以在Div等标签中嵌入。HtmlTableHelper是一个自己写的类,代码很简单。
}
public void RaiseCallbackEvent(string eventArgument)
{
if (String.IsNullOrEmpty(eventArgument)) return;
list = ProductRepository.GetProducts(eventArgument);
}
}
客户端代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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 runat="server">
<title>Demo Auto-Suggest Callback</title>
<link href="Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<div>
<strong><span style="font-size: 14pt">使用客户端回调实现自动完成功能<br />
<br />
</span></strong>
<br />
输入产品名称: <input type="text" onkeydown ="return GetKeyType(event)" onkeyup ="return GetProducts(event)" id="txtSearch" name="txtSearch" />
<div id="results">
</div>
</div>
</form>
</body>
</html>
<script language="javascript" type="text/javascript">
var word = '';
var UP = 38;
var DOWN = 40;
var ENTER = 13;
var index = -1;
var TAB = 9;
var BACKSPACE = 8;
var table = null;
var rows = null;
var selectedRow = null;
function GetKeyType(e)
{
var keynum;
if(window.event)
{
keynum=e.keyCode;
}
else if(e.which)
{
keynum=e.which;
}
if(keynum == ENTER)
return false;
}
function GetProducts(e)
{
var keynum
var keychar
var numcheck
if(window.event) // IE
{
keynum = e.keyCode
}
else if(e.which) // Netscape/Firefox/Opera
{
keynum = e.which
}
keychar = String.fromCharCode(keynum)
numcheck = //d/
// If the down key is pressed
if(keynum == DOWN)
{
MoveCursorDown();
return;
}
else if(keynum == UP)
{
MoveCursorUp();
return;
}
else if(keynum == ENTER)
{
if(selectedRow!=null)
{
if(IsFireFox())
{
if(selectedRow.childNodes[1].innerHTML!='')
{
document.getElementById("txtSearch").value = selectedRow.childNodes[1].innerHTML;
}
}
else
{
if(selectedRow.innerText!='')
document.getElementById("txtSearch").value = selectedRow.innerText;
}
document.getElementById("results").innerHTML = '';
}
// false is returned so that the postback won't occur when the return key is pressed
return false;
}
word=document.getElementById("txtSearch").value;
// Call the server side method
CallServer(word,'');
}
function IsFireFox()
{
return (navigator.appName == 'Netscape');
}
function MoveCursorUp()
{
selectedRow = null;
table = document.getElementById("MyTable");
if(table == null) return;
rows = table.getElementsByTagName("TR");
if(index > 0)
{
index--;
}
SetDefaultRowColor();
selectedRow = rows[index];
selectedRow.className = 'HighlightRow'
}
function MoveCursorDown()
{
selectedRow = null;
table = document.getElementById("MyTable");
if(table == null) return;
rows = table.getElementsByTagName("TR");
if(index < rows.length)
{
if(index < rows.length -1)
{
index++;
}
SetDefaultRowColor();
selectedRow = rows[index];
selectedRow.className = 'HighlightRow';
}
}
function SetDefaultRowColor()
{
for(i=0;i<rows.length;i++)
{
rows[i].className = 'DefaultRowColor';
}
}
function RecieveServerData(response)
{
document.getElementById("results").innerHTML = response;
}
</script>