程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> ASP.NET基礎 >> ASP.Net中英文復合檢索文本框實現思路及代碼

ASP.Net中英文復合檢索文本框實現思路及代碼

編輯:ASP.NET基礎

前段時間,寫一個用戶部門的管理頁面,需要對後台獲取的用戶數據實現英漢檢索功能。 

同時,選定一個選項之後,需要觸發事件與後台交互,將該用戶所在的部門顯示到頁面右邊的ListBox控件中。

   

 

一、Dojo的FilteringSelect組件實現拼音檢索功能

在網上有不少相關的介紹,其中比較經典的有"海盜亂語"的關於重寫Dojo的FilteringSelect組件實現拼音檢索功能的介紹(地址http://cosbor.web-144.com/?p=38、http://cosbor.web-144.com/?p=52)。由於作者的Demo後台以及pinyin4j的jar包都是基於Java平台的,本人花了一點時間將其實現在.Net平台下,並成功的實現了FilteringSelect選中事件的注冊。實現原理請詳細參考"海盜亂語"博客中的分析,這裡對.Net平台下的實現思路做簡要說明,並貼出源碼供大家參考(在此對作者提供的思路表示感謝!):

首先,引入Dojo工具包,在dojo目錄下添加一個"test"文件夾,新建一個FilteringSelect.js文件,如下圖:

FilteringSelect.js文件的作用是重寫FilteringSelect組件,"海盜亂語"的博文中給出了的代碼清單,為方便起見轉貼如下:
復制代碼 代碼如下:
define([
"dojo/_base/declare", // declare,
"dojo/dom-attr", // domAttr.get
"dijit/form/FilteringSelect"
], function(declare, domAttr ,FilteringSelect){

return declare("test.FilteringSelect", [FilteringSelect], {

displayValueAttr:null, //新增一個自定義屬性,用於指定FilteringSelect的textbox中最終顯示內容的屬性字段

// summary:
// 覆蓋dijit.form._AutoCompleterMixin的同名方法,使FilteringSelect支持displayValueAttr指定textbox最終顯示內容,而不是默認顯示searchAttr指定的字段內容
_announceOption: function(/*Node*/ node){

if(!node){
return;
}
// pull the text value from the item attached to the DOM node
var newValue;
if(node == this.dropDown.nextButton ||
node == this.dropDown.previousButton){
newValue = node.innerHTML;
this.item = undefined;
this.value = '';
}else{
var item = this.dropDown.items[node.getAttribute("item")];
var displayAttr = this.displayValueAttr!=null?this.displayValueAttr:this.searchAttr;//此處判斷是否配置了自定義屬性displayValueAttr

newValue = (this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API)
this.store.getValue(item, displayAttr) : item[displayAttr]).toString();//將this.searchAttr替換為displayAttr

this.set('item', item, false, newValue);
}
// get the text that the user manually entered (cut off autocompleted text)
this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
// set up ARIA activedescendant
this.focusNode.setAttribute("aria-activedescendant", domAttr.get(node, "id"));
// autocomplete the rest of the option to announce change
this._autoCompleteText(newValue);
},

});
});

然後,新建一個WebForm頁面,放置一個FilteringSelect控件,數據源取值為頁面類繼承過來的userListstr字段,頁面前台代碼如下: 
復制代碼 代碼如下:
<%@ Page Title="" Language="C#" AutoEventWireup="true" CodeFile="OrgRelation.aspx.cs" Inherits="OrgRelation" %>

<!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></title>
<script src="Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript"></script>
<link href="Scripts/dojo/dijit/themes/claro/claro.css" rel="stylesheet" type="text/css" />
<link href="Scripts/dojo/dojo/resources/dojo.css" rel="stylesheet" type="text/css" />
<script src="Scripts/dojo/dojo/dojo.js" type="text/javascript"></script>

<script type="text/javascript">
//參數設置
require([
'test/FilteringSelect',
'dojo/store/Memory',
'dojo/domReady!'
], function (FilteringSelect, Memory) {

var jsonstr = '<%=userListStr%>';
var json = jQuery.parseJSON(jsonstr);
var obj = {data:""};
obj['data'] = json;
var selectStore = new Memory(obj);
//創建FilteringSelect
var testSelect = new FilteringSelect({
id: "testSelect",
name: "test",
value: "",
store: selectStore,
searchAttr: 'py', //指定輸入文本框進行用來進行檢索的字段
labelAttr: 'name', //指定下拉菜單中顯示的字段
displayValueAttr: 'name', //指定選中下拉菜單後顯示在輸入框中的字段
required: false,
autoComplete: false
}, "testSelect");

});

//注冊失去焦點事件
window.onload = function () {

function selblur() {
var guid = dijit.byId('testSelect').attr('value');
alert(guid);
window.location.href = "OrgRelation.aspx?userId=" + guid;
return false;
}
var sel = dojo.byId("testSelect");
dojo.connect(sel, "onblur", selblur);
};
</script>

</head>
<body>
<form id="Form1" method="post" runat="server">
<div align="center" id="title">
<strong>編輯用戶部門關系</strong>
</div>

<div style="text-align: center;width: 100%;padding-top: 100px;font-size:15px;">選擇用戶:<input id="testSelect"/>
</div>

</form>
</body>
</html>

最後,在頁面加載事件中獲取用戶數據,序列化之後,賦給protected類型的userListstr字段。其中這裡引用到微軟提供的獲取漢字拼音的類庫ChnCharInfo.dll,代碼請單如下:
復制代碼 代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.International.Converters.PinYinConverter;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;

public partial class OrgRelation : System.Web.UI.Page
{
protected string userListStr = string.Empty;

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GetUsers();
}
}

//與前台頁面Json對象格式對應的類
public class UserInfo
{
public string name { get; set; }
public string id { get; set; }
public string py { get; set; }
}

protected void GetUsers()
{
//獲取用戶信息,及每項記錄的拼音簡碼
List<User> list =new BLL.User().GetUsers();
List<UserInfo> UserInfoList = new List<UserInfo>();
foreach (User item in list)
{
UserInfo userInfo= new UserInfo();
userInfo.id = item.UserId;
userInfo.name = item.User Name;
userInfo.py = GetPY(item.UserName);
UserInfoList .Add(userInfo);
}
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
//執行序列化 並賦值
userListStr = jsonSerializer.Serialize(UserInfoList);
}

#region 拼音檢索的相關方法
/// <summary>
/// 獲得一個漢字字符的拼音的字符串集合,並處理聲調和空值
/// </summary>
/// <param name="ch">漢字字符</param>
/// <returns></returns>
public static List<string> GetPinyins(char ch)
{
List<string> list = new List<string>();
ChineseChar cc = new ChineseChar(ch); //獲得包含漢字信息的對象
foreach (string item in cc.Pinyins)
{
if (item != null)
{
string temp = item.Substring(0, item.Length - 1);
if (!list.Contains(temp))
{
list.Add(temp);
}
}
}
return list;
}
/// <summary>
/// 得到一個詞組的拼音的首字母字符串(多音取第一個)
/// </summary>
/// <returns></returns>
public static string GetPY(string str)
{
Regex reg = new Regex(@"[\u4e00-\u9fa5]");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
string ch = str[i].ToString();
if (reg.IsMatch(ch))
{
string s = GetPinyins(str[i])[0];
sb.Append(s[0]);
}
else
{
sb.Append(ch);
}
}
return sb.ToString();
}
#endregion
}

這樣拼音檢索的功能就完成了。不過有兩點不盡人意的地方:1.使用拼音檢索後,不好再使用中文檢索,2.網上查了很久,沒有選中項改變事件介紹,代碼中只是注冊了一個失去焦點事件,在與後台交互方面不太方便(可能是本人對dojo事件不熟,歡迎對dojo api有研究的大俠指點)。

二、JqueryUI的autocomplete插件實現拼音檢索功能

其實JqueryUI也提供了一個非常好用的插件--autocomplete,它與ChnCharInfo.dll類庫配合使用,不僅能實現同樣優秀的檢索功能,而且能夠很好的解決上述兩個問題。不妨來看看:

需要用到的相關組件和引用的類庫:Jquery-UI 、漢字拼音轉換語言包類庫ChnCharInfo .dll和Json對象序列化類庫Newtonsoft.Json.dll,如下所示:

 

1.WebForm的aspx頁面實現:

首先引入jquery-1.8.2.js、jquery-ui-1.9.0.custom.js、jquery-ui-1.9.0.custom.css,然後在頁面加載完成的事件中寫如下腳本:
復制代碼 代碼如下:
<script type="text/javascript">
$(function () {
$("#selCompate").autocomplete({
source: "GetUser.ashx",
minLength: 1,
//以下為選中事件
select: function (event, ui) {
temp = ui.item;
$("#hidcontactid").val(temp.id);
$("#hidcontactname").val(temp.label);
$("#form2").attr("action", "./OrgRelation.aspx?contactId=" + temp.id + "&contactName=" + temp.label);
$("#form2").submit();
}
});
$("#selCompate").val($("#hidcontactname").val())
});
</script>

其中第4行的 source: "GetUser.ashx",是指鍵入字符後,發送異步請求的地址,GetUser.ashx負責向請求的客戶端提供滿足Json格式的用戶信息;第5行的minLength: 是輸入到幾個字符時開始發送異步請求;第7行的select: function(event, ui){}即選中事件,ui.item表示被選中的項;第8-9行的隱藏域存值,是為了頁面刷新後能重新獲取該選中項的相關信息,重新寫回頁面以備用;第10-11行以當前選中項的id和label被為參數向OrgRelation.aspx發送post請求,是實現將選中用戶的所在部門查詢處來,顯示到頁面右側的ListBox控件中,其服務端實現與本次討論的內容無關,代碼就不貼出來了。

頁面的完整代碼清單如下:
復制代碼 代碼如下:
<%@ Page Title="" Language="C#" AutoEventWireup="true" CodeFile="OrgRelation.aspx.cs"
Inherits="OrgRelation"%>

<!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></title>
<script src="Scripts/jquery-1.8.2.js" type="text/javascript"></script>
<script src="Scripts/jquery-ui-1.9.0.custom.js" type="text/javascript"></script>
<link href="css/ui-lightness/jquery-ui-1.9.0.custom.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
$(function () {
$("#selCompate").autocomplete({
source: "GetUser.ashx",
minLength: 1,
//以下為選中事件
select: function (event, ui) {
temp = ui.item;
$("#hidUserId").val(temp.id);
$("#hidUserName").val(temp.label);
$("#form2").attr("action", "./OrgRelation.aspx?UserId=" + temp.id + "&UserName=" + temp.label);
$("#form2").submit();
}
});
$("#selCompate").val($("#hidUserName").val())
});
</script>
</head>
<body>
<form id="form2" method="post" action="./OrgRelation.aspx" name="sendForm"></form>
<form id="Form1" method="post" runat="server" >
<input type="hidden" id="hidUserId" name="hidUserId" value="<%=currentUserId%>" />
<input type="hidden" id="hidUserName" name="hidUserName" value="<%=currentUserName%>"/>

<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div id="outline">
<div align="center" id="title">
<strong>編輯用戶部門關系</strong>
</div>
<div id="main">
<table align="center">
<tr>
<td>
<div>
<b>選擇用戶:</b> 
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<input type="text" id="selCompate" style="line-height: 10px; margin-top: 0px;
margin-left: 0px; height: 23px;"
runat="server" />
</ContentTemplate>
</asp:UpdatePanel><br />
<b>選擇部門:</b>
</div>
<br />
</td>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td valign="top" width="41%">
<div id="left">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TreeView ID="TreeViewOrgData" runat="server" Font-Names="微軟雅黑" Height="385px"
Font-Size="11pt" ForeColor="Black" BackColor="AliceBlue" OnTreeNodeCollapsed="TreeViewOrgData_TreeNodeCollapsed"
OnTreeNodeExpanded="TreeViewOrgData_TreeNodeExpanded" ShowCheckBoxes="All">
</asp:TreeView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</td>
<td align="center" valign="middle" width="18%">
<p>

<asp:Button ID="btnAddOrg" runat="server" Width="85px" Text="添加部門 >>" Height="22px"
BorderStyle="Solid" BorderColor="DarkGray" BackColor="GhostWhite" Font-Size="9pt"
OnClick="btnAddOrg_Click"></asp:Button></p>
<p>
<asp:Button ID="btnRemoveOrg" runat="server" Width="85px" Text="<< 移除部門" Height="22px"
BorderStyle="Solid" BorderColor="DarkGray" BackColor="GhostWhite" Font-Size="9pt"
OnClick="btnRemoveOrg_Click"></asp:Button></p>

</td>
<td valign="top" align="center" width="41%">
<div id="right">
<asp:ListBox ID="LBOrg" runat="server" Width="300px" Height="350px" Rows="13" BackColor="AliceBlue"
Font-Size="11pt" SelectionMode="Multiple" >
</asp:ListBox>
</div>
</td>
</tr>
</table>
</div>
<br />
<div align="center" id="bottom">
<asp:Button ID="btnBack" runat="server" Text="·返 回·" BackColor="#f8f8ff" />  
<asp:Button ID="btnSave" runat="server" Text="·保 存·" BackColor="#f8f8ff"
onclick="btnSave_Click" />
</div>
</div>
</form>
</body>
</html>

2.Global.asax中用戶數據的准備

由於這裡的用戶數據不經常變化,考慮到搜索是需要頻繁的向服務端請求數據,因此將用戶數據存入了Application中,這樣搜索時直接從Application中取,不用每次去數據庫查詢。

Application對象的賦值是在全局應用程序Global.asax的 Application_Start事件中完成的,代碼如下:
復制代碼 代碼如下:
void Application_Start(object sender, EventArgs e)
{
Application.Lock();
Application["User"] = GetUsers();
Application.UnLock();
}

獲取用戶信息的GetUser方法中,同時完成了拼音簡碼的獲取,代碼如下:
復制代碼 代碼如下:
protected List<string> GetUsers()
{
List<Model.User> list = new BLL.User().GetUsers();
List<string> UserList = new List<string>();
foreach (Model.User item in list)
{
UserList .Add(item.Id+"|"+item.Name+"|"+GetPY(item.Name).Replace(" ","").ToLower());
}
return UserList ;
}

/// <summary>
/// 獲得一個漢字字符的拼音的字符串集合,並處理聲調和空值
/// </summary>
/// <param name="ch">漢字字符</param>
/// <returns></returns>
public static List<string> GetPinyins(char ch)
{
List<string> list = new List<string>();
Microsoft.International.Converters.PinYinConverter.ChineseChar cc = new Microsoft.International.Converters.PinYinConverter.ChineseChar(ch); //獲得包含漢字信息的對象
foreach (string item in cc.Pinyins)
{
if (item != null)
{
string temp = item.Substring(0, item.Length - 1);
if (!list.Contains(temp))
{
list.Add(temp);
}
}
}
return list;
}
/// <summary>
/// 得到一個詞組的拼音的首字母字符串(多音取第一個)
/// </summary>
/// <returns></returns>
public static string GetPY(string str)
{
Regex reg = new Regex(@"[\u4e00-\u9fa5]");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
string ch = str[i].ToString();
if (string.IsNullOrEmpty(ch))
{

}
else if (reg.IsMatch(ch))
{
string s = GetPinyins(str[i])[0];
sb.Append(s[0]);
}
else
{
sb.Append(ch);
}
}
return sb.ToString();
}

至於Application與數據庫中數據的一致的考慮,可提供一個一般處理程序UpdateApplication.ashx負責更新Application(代碼與Global.asax中基本相同),當數據庫發生變化時,訪問UpdateApplication.ashx即可更新Application["Contact"]對象。

3.GetUser.ashx中返回符合檢索條件的數據

GetUser.ashx中響應搜索事件的服務端代碼清單如下:
復制代碼 代碼如下:
<%@ WebHandler Language="C#" Class="GetUser" %>

using System;
using System.Web;
using BLL;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using Microsoft.International.Converters.PinYinConverter;

public class GetUser :JavaScriptSerializer,IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
int i = 0;
List<string> strlist = context.Application["User"] as List<string>;
string inputStr = context.Request.QueryString.Get("term").ToLower();
List<UserItem> userList = new List<UserItem>();

foreach (string str in strlist)
{
string[] userArr = str.Split('|');
if (i < 10)
{
Regex reg = new Regex(@"^" + inputStr);
if (reg.IsMatch(userArr[2]) || reg.IsMatch(userArr[1]))
{
UserItem item = new UserItem();
item.id = userArr[0];
item.label = userArr[1];
item.value = userArr[2];
userList.Add(item);
i++;
}
}
else
{
break;
}
}

context.Response.ContentType = "application/json";
string output = Newtonsoft.Json.JsonConvert.SerializeObject(userList);
context.Response.Write(output);
}

public bool IsReusable
{
get
{
return false;
}
}
}

public class UserItem
{
public string id { get; set; }
public string label { get; set; }
public string value { get; set; }
}

第17行是獲取文本框中輸入的檢索字符串inputstr,這裡使用正則表達式對獲取名稱以inputstr開頭的記錄(中文檢索)或者拼音簡碼以inputstr開頭的記錄(拼音檢索)。如果需要模糊檢索功能,可以修改第25行的正則表達式為:Regex reg = new Regex(inputStr);即可。如果需要更多字段的復合檢索(例如用戶手機號,郵箱地址等),也只要Application對像賦值時獲取相關的字段信息,在26行的if判斷中增加相應匹配項即可。

其中UserItem是為頁面提供Json對象的類,label是必須字段,搜索框中顯示的內容即該字段的值。得到符合條件的數據集合後,需要使用Newtonsoft.Json.JsonConvert的SerializeObject方法進行序列化,再返回給客戶端。

到此,即實現了本文開篇的貼圖效果。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved