用客户端回调实现自动完成功能

来源:互联网 发布:mysql查看表空间大小 编辑:程序博客网 时间:2024/05/16 05:07

最近在一个项目中 ,需要填写行政区划,为了防止用户填写错误,应该用下拉选择来代替文本输入,但全国的行政区划有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>

 整个系统的执行过程如下图: