ASP.Net中英文复合检索文本框实现思路及代码

 更新时间:2021年9月22日 10:16  点击:1315

前段时间,写一个用户部门的管理页面,需要对后台获取的用户数据实现英汉检索功能。 

同时,选定一个选项之后,需要触发事件与后台交互,将该用户所在的部门显示到页面右边的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>&nbsp;
<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" />&nbsp;&nbsp;
<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方法进行序列化,再返回给客户端。

到此,即实现了本文开篇的贴图效果。

[!--infotagslink--]

相关文章

  • php 中英文混合字符串截取

    文章介绍一个实用的函数,我们如果用php substr来截取字符在中文上处理的很有问题,今天自己写了一个比较好的中文与英文字符截取的函数,有需要的朋友可以参考下。 ...2016-11-25
  • C#实现windows form限制文本框输入的方法

    这篇文章主要介绍了C#实现windows form限制文本框输入的方法,涉及C#限制文本框输入的技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • js实现文本框输入文字个数限制代码

    这篇文章主要介绍了js实现文本框输入文字个数限制代码,文本框输入的文字个数并不是无限制的,一般都会限定一个输入最高上限,如何限制,请看本文...2015-12-27
  • JS清除文本框内容离开在恢复及鼠标离开文本框时触发js的方法

    多网站的需要填写的文本框在默认状态下都会给出一个默认的提示语言,当鼠标点击此文本框的时候能够将里面的默认文本清除,当删除输入的文本且焦点离开文本框的时候再将默认的文本写入文本框...2016-01-14
  • 深度解析MySQL 5.7之中文全文检索

    InnoDB默认的全文索引parser非常合适于Latin,因为Latin是通过空格来分词的。但对于像中文,日文和韩文来说,没有这样的分隔符。一个词可以由多个字来组成,所以我们需要用不同的方式来处理。在MySQL 5.7.6中我们能使用一个新的全文索引插件来处理它们:n-gram parser。...2017-01-09
  • 设置点击文本框或图片弹出日历控件的实现代码

    下面小编就为大家带来一篇设置点击文本框或图片弹出日历控件的实现代码。小编觉得挺不错的,现在分享给大家,也给大家做个参考,一起跟随小编过来看看吧...2016-05-14
  • C#实现中英文混合字符串截取的方法

    这篇文章主要介绍了C#实现中英文混合字符串截取的方法,是C#字符串操作的常用方法,需要的朋友可以参考下...2020-06-25
  • elasticsearch+logstash并使用java代码实现日志检索

    这篇文章主要介绍了elasticsearch+logstash并使用java代码实现日志检索,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-22
  • HTML文本框的值改变后触发后台代码的方法

    asp.net用日期插件,当选中一个日期时触发一个事件,以查询当前日期的数据。这是要跟数据库交互的。先贴出控件代码:...2020-06-25
  • C# 检索不区分大小写并高亮显示实例详解

    这篇文章主要介绍了C# 检索不区分大小写并高亮显示实例详解的相关资料,需要的朋友可以参考下...2020-06-25
  • PHP针对中英文混合字符串长度判断及截取方法示例

    这篇文章主要介绍了PHP针对中英文混合字符串长度判断及截取方法,结合实例形式分析了php中英文字符串的遍历、转换、截取、计算等相关操作技巧,需要的朋友可以参考下...2017-04-03
  • php mb_strwidth函数实现中英文混排字符串截取

    如果是简单的字符截取我们常用的就substr函数或再使用mb_substr来截取字符了,但是我们有时会发现有中英文混排字符串截取时并不像那么简单,因这样我们需要考虑到编码问...2016-11-25
  • C#中英文混合字符串截取函数

    这篇文章介绍了C#中英文混合字符串截取函数,有需要的朋友可以参考一下...2020-06-25
  • php获取复选框 文本框、密码域、隐藏域、按钮、文本域值实例

    复选框能够进行项目的多项选择,浏览者在填写一些表单时,有时需要选择多个项目(如:兴趣爱好等) 复选框一般是多个同时存在,为了便于传值,name的名字可以定义为数组形...2016-11-25
  • 如何禁止文本框的记忆功能方法集锦

    IE提供了一个自动完成功能可以记忆我们的输入内容(如帐号等),方便下一次快速地录入类似资料.这确实是一个非常友好的功能, 在操作时只需用鼠标双击文本框或输入前几个字符, 系统会自动列出以前的录入历史供你选择, 大大提高录入速度及准确性....2021-09-22
  • php 批量添加多行文本框textarea一行一个

    复制代码 代码如下: $act=!empty($_GET['act']) ? trim($_GET['act']) : ''; switch($act) { case 'adda': $area['a_value'] = trim($_POST['a_value']); $area['a_type']=3; if(strpos($area['a_value&...2014-06-07
  • Ajax+asp.net智能匹配检索(含图含完整代码)

    使用谷歌搜索引擎的用户都知道,只要在文本框中输入部分关键字,就能显示相关搜索提示信息列表...2021-09-22
  • 基于jQuery实现文本框只能输入数字(小数、整数)

    在实际应用中,文本框中有时候只能够允许输入整数,但是有时候可能更为"博爱"一点,可以允许输入浮点数,下面就通过实例代码介绍一下如何利用jquery实现此功能 ...2016-01-15
  • opencv3/C++ PHash算法图像检索详解

    今天小编就为大家分享一篇opencv3/C++ PHash算法图像检索详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
  • 浅析MongoDB 全文检索

    这篇文章主要介绍了MongoDB 全文检索的相关资料,文中讲解非常细致,帮助大家更好的学习了解MongoDB,感兴趣的朋友可以了解下...2020-12-08