zoukankan      html  css  js  c++  java
  • ASP.Net中实现中英文复合检索文本框

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

           

      同时,选定一个选项之后,需要触发事件与后台交互,将该用户所在的部门显示到页面右边的ListBox控件中。

             

            

      一、Dojo的FilteringSelect组件实现拼音检索功能

      在网上有不少相关的介绍,其中比较经典的有"海盗乱语"的关于重写Dojo的FilteringSelect组件实现拼音检索功能的介绍(地址http://cosbor.web-144.com/?p=38http://cosbor.web-144.com/?p=52)。由于作者的Demo后台以及pinyin4j的jar包都是基于Java平台的,本人花了一点时间将其实现在.Net平台下,并成功的实现了FilteringSelect选中事件的注册。实现原理请详细参考"海盗乱语"博客中的分析,这里对.Net平台下的实现思路做简要说明,并贴出源码供大家参考(在此对作者提供的思路表示感谢!):

      首先,引入Dojo工具包,在dojo目录下添加一个"test"文件夹,新建一个FilteringSelect.js文件,如下图:

          

      FilteringSelect.js文件的作用是重写FilteringSelect组件,"海盗乱语"的博文中给出了的代码清单,为方便起见转贴如下:

    View Code
    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字段,页面前台代码如下:   

    View Code
     <%@ 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; 100%;padding-top: 100px;font-size:15px;">选择用户:<input id="testSelect"/>
             </div>
     
         </form>
     </body>
     </html>

      最后,在页面加载事件中获取用户数据,序列化之后,赋给protected类型的userListstr字段。其中这里引用到微软提供的获取汉字拼音的类库ChnCharInfo.dll,代码请单如下:  

    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Web;
     5 using System.Web.UI;
     6 using System.Web.UI.WebControls;
     7 using Microsoft.International.Converters.PinYinConverter;
     8 using System.Text;
     9 using System.Text.RegularExpressions;
    10 using System.Web.Script.Serialization;
    11 
    12 public partial class OrgRelation : System.Web.UI.Page
    13 {
    14     protected string userListStr = string.Empty;
    15 
    16     protected void Page_Load(object sender, EventArgs e)
    17     {
    18         if (!IsPostBack)
    19         {
    20             GetUsers();
    21         }
    22     }
    23 
    24     //与前台页面Json对象格式对应的类
    25    public class UserInfo
    26     {
    27         public string name { get; set; }
    28         public string id { get; set; }
    29         public string py { get; set; }
    30     }
    31 
    32     protected void GetUsers()
    33     {
    34         //获取用户信息,及每项记录的拼音简码
    35         List<User> list =new BLL.User().GetUsers();
    36         List<UserInfo> UserInfoList = new List<UserInfo>();
    37         foreach (User item in list)
    38         {
    39             UserInfo userInfo= new UserInfo();
    40             userInfo.id = item.UserId;
    41             userInfo.name = item.User Name;
    42             userInfo.py = GetPY(item.UserName);
    43             UserInfoList .Add(userInfo);
    44         }
    45         JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
    46         //执行序列化 并赋值
    47         userListStr = jsonSerializer.Serialize(UserInfoList);
    48     }
    49 
    50     #region 拼音检索的相关方法
    51    /// <summary>
    52     /// 获得一个汉字字符的拼音的字符串集合,并处理声调和空值
    53    /// </summary>
    54     /// <param name="ch">汉字字符</param>
    55     /// <returns></returns>
    56     public static List<string> GetPinyins(char ch)
    57     {
    58         List<string> list = new List<string>();
    59         ChineseChar cc = new ChineseChar(ch); //获得包含汉字信息的对象
    60         foreach (string item in cc.Pinyins)
    61         {
    62             if (item != null)
    63             {
    64                 string temp = item.Substring(0, item.Length - 1);
    65                 if (!list.Contains(temp))
    66                 {
    67                     list.Add(temp);
    68                 }
    69             }
    70         }
    71         return list;
    72     }
    73     /// <summary>
    74     /// 得到一个词组的拼音的首字母字符串(多音取第一个)
    75     /// </summary>
    76     /// <returns></returns>
    77     public static string GetPY(string str)
    78     {
    79         Regex reg = new Regex(@"[\u4e00-\u9fa5]");
    80         StringBuilder sb = new StringBuilder();
    81         for (int i = 0; i < str.Length; i++)
    82         {
    83             string ch = str[i].ToString();
    84             if (reg.IsMatch(ch))
    85             {
    86                 string s = GetPinyins(str[i])[0];
    87                 sb.Append(s[0]);
    88             }
    89             else
    90             {
    91                 sb.Append(ch);
    92             }
    93         }
    94         return sb.ToString();
    95     }
    96     #endregion
    97 }           

      这样拼音检索的功能就完成了。不过有两点不尽人意的地方: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,然后在页面加载完成的事件中写如下脚本:

     1     <script type="text/javascript">
     2         $(function () {
     3                         $("#selCompate").autocomplete({
     4                             source: "GetUser.ashx",
     5                             minLength: 1,
     6                             //以下为选中事件
     7                             select: function (event, ui) {
     8                                 temp = ui.item;
     9                                 $("#hidUserId").val(temp.id);
    10                                 $("#hidUserName").val(temp.label);
    11                                 $("#form2").attr("action", "./OrgRelation.aspx?contactId=" + temp.id + "&contactName=" + temp.label);
    12                                 $("#form2").submit();
    13                             }
    14                         });
    15             $("#selCompate").val($("#hidUserName").val())
    16         });
    17     </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控件中,其服务端实现与本次讨论的内容无关,代码就不贴出来了。

      页面的完整代码清单如下:

    View Code
    <%@ 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中响应搜索事件的服务端代码清单如下:

      

     1 <%@ WebHandler Language="C#" Class="GetUser" %>
     2 
     3 using System;
     4 using System.Web;
     5 using BLL;
     6 using System.Collections.Generic;
     7 using System.Text.RegularExpressions;
     8 using System.Web.Script.Serialization;
     9 using Microsoft.International.Converters.PinYinConverter;
    10 
    11 public class GetUser :JavaScriptSerializer,IHttpHandler
    12 {
    13     public void ProcessRequest(HttpContext context)
    14     {
    15         int i = 0;
    16         List<string> strlist = context.Application["User"] as List<string>;
    17         string inputStr = context.Request.QueryString.Get("term").ToLower();
    18         List<UserItem> userList = new List<UserItem>();
    19         
    20         foreach (string str in strlist)
    21         {
    22             string[] userArr = str.Split('|');
    23             if (i < 10)
    24             {
    25                 Regex reg = new Regex(@"^" + inputStr);
    26                 if (reg.IsMatch(userArr[2]) || reg.IsMatch(userArr[1]))
    27                 {
    28                     UserItem item = new UserItem();
    29                     item.id = userArr[0];
    30                     item.label = userArr[1];
    31                     item.value = userArr[2];
    32                     userList.Add(item);
    33                     i++;
    34                 }
    35             }
    36             else
    37             {
    38                 break;
    39             }
    40         }
    41         
    42         context.Response.ContentType = "application/json";
    43         string output = Newtonsoft.Json.JsonConvert.SerializeObject(userList);
    44         context.Response.Write(output);
    45     }
    46 
    47     public bool IsReusable
    48     {
    49         get
    50         {
    51             return false;
    52         }
    53     }
    54 }
    55 
    56 public class UserItem
    57 { 58 public string id { get; set; } 59 public string label { get; set; } 60 public string value { get; set; } 61 }

      第17行是获取文本框中输入的检索字符串inputstr,这里使用正则表达式对获取名称以inputstr开头的记录(中文检索)或者拼音简码以inputstr开头的记录(拼音检索)。如果需要模糊检索功能,可以修改第25行的正则表达式为:Regex reg = new Regex(inputStr);即可。如果需要更多字段的复合检索(例如用户手机号,邮箱地址等),也只要Application对像赋值时获取相关的字段信息,在26行的if判断中增加相应匹配项即可。

      其中UserItem是为页面提供Json对象的类,label是必须字段,搜索框中显示的内容即该字段的值。得到符合条件的数据集合后,需要使用Newtonsoft.Json.JsonConvert的SerializeObject方法进行序列化,再返回给客户端。

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

      

  • 相关阅读:
    IBM小练习
    面向对象
    面向对象_人狗大战
    面向对象组合小练习
    面向对象小作业
    作业大礼包_员工信息表
    异常报错处理
    开发规范

    U-boot工作流程分析
  • 原文地址:https://www.cnblogs.com/Extreme/p/Extreme_ChnCharSearch.html
Copyright © 2011-2022 走看看