原文:通通WPF随笔(1)——基于lucene.NET让ComboBox拥有强大的下拉联想功能


  我一直很疑惑百度、谷哥搜索框的下拉联想功能是怎么实现的?是不断地查询数据库吗?其实到现在我也不知道,他们是怎么实现这么高效的。后来在博客园无意邂逅了“鹿神”,搜索引擎唉,听起来就很高端。于是研究了一段时间后就产生了这个WPF的下拉联想控件。

名称:

简拼:

全拼:

区号:

邮编:

  这么强大的功能代码一定会复杂吧?不是的哦,亲~代码只有短短几句哦

界面如下:(下拉框后面的数字为查询的延时,可见效率还是很高滴)

XAML:

<cop:CopAutoCompleted url="{Binding Text, ElementName=DirTextBox}" columnNames="{Binding Text, ElementName=UCSearchColTextBox}" 
textName="{Binding Text, ElementName=TextNameTextBox}" maxItems="{Binding Text, ElementName=TextNameTextBox_Copy}">
<cop:CopAutoCompleted.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding City}" />
<TextBlock Text=" (" Foreground="#FF383838"/>
<TextBlock Text="{Binding Spell}" Foreground="#FF383838" />
<TextBlock Text=")" Foreground="#FF383838"/>
</StackPanel>
</DataTemplate>
</cop:CopAutoCompleted.ItemTemplate>
</cop:CopAutoCompleted>

属性介绍:(该控件继承于ComboBox,只是多了下面4个属性)

  url:设置索引所在的文件夹(稍后会介绍如何创建索引)

  columnNames:设置需要检索的列名

  textName:选择下拉项后显示在text里的列名

  maxItems:下拉框最多显示多少项(如果显示内容过多的话会有延时的感觉,经测试延时是由于后台banding的数据集合改变跟新到界面时产生的,不是lucene的效率问题)

  ItemTemplate:玩WPF的都懂的,设置下拉显示数据的布局内容。这样的话就有了很高的可扩展性和灵活性。

 

1.总体思路


  (1)创建lucene索引:在网上找一个全国城市的数据库,用代码提取出来,分别对里面的各列创建索引。

  (2)查询索引:通过lucene的PrefixQuery类构造查询语句,就可以实现前缀查询出整体。

  (3)ComboBox绑定:这里数据源绑定到ObservableCollection<dynamic>集合(自动通知,方便啊),而其中的每一项为根据查询出的每一项结果动态构造的对象。所以用到dynamic运行时解析。

  

2.详细设计


  基本知识我这里就不详细说了,可参看文章最后的参考文献。

1、创建lucene索引

  我在网上找全国城市数据库时找找到的一个比较全面的是Access的,所以这里特地写了一个创建索引的功能:

  (之前比较流行通用数据库访问层,我基于反射自己写了一个通用数据库DBHelper,由于电脑上没有数据库环境,所以只测试了Access和Sqlite)

  其实就是根据查询结果,对需要创建索引的列添加lucene的索引。代码如下:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
//设置索引文件夹
var directory = FSDirectory.GetDirectory(DirTextBox.Text, true); //创建一个索引,采用StandardAnalyzer对句子进行分词
IndexWriter indexWriter = new IndexWriter(directory, new StandardAnalyzer()); var columnName= ColumnNameTextBox.Text.Split(','); //设置数据库连接字符串
if (ComboBox1.Text=="Sqlite")
{
helper=new CopDb.CopDbHelper(CopDb.CopDbHelper.CopDbType.Sqlite,ConnTestBox.Text);
}
if (ComboBox1.Text=="Access")
{
helper = new CopDb.CopDbHelper(CopDb.CopDbHelper.CopDbType.Access, ConnTestBox.Text);
} int timeOut = Environment.TickCount;
var read = helper.ExecuteReader(SQLStrTextBox.Text);
SqlTimeTextBox.Text = (Environment.TickCount - timeOut).ToString();
while (read.Read())
{
//创建文档
Document doc = new Document();
//添加字段
foreach (var item in columnName)
{
doc.Add(new Field(item, read[item].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
}
indexWriter.AddDocument(doc);
}
read.Close(); //对索引文件进行优化
indexWriter.Optimize();
indexWriter.Close();
MessageBox.Show("创建索引完成");
}

2、查询索引

  

  就是构造lucene查询query时用PrefixQuery类就行,如下:

 var cols = SearchColTextBox.Text.Split(',');

            BooleanQuery query = new BooleanQuery();

            foreach (var item in cols)
{
query.Add(new PrefixQuery(new Term(item, SearchTextBox.Text)),BooleanClause.Occur.SHOULD);
}
//query.parse:注入查询条件
var hits = search.Search(query);

3、ComboBox绑定数据源

  

  数据源为ObservableCollection<dynamic>类型集合,后台我们只用动态构造出每一个查询对象添加进集合里即可。初始化dynamic对象时还不能用ExpandoObject,虽然ExpandoObject很方便,但是这是一个封闭类,不能继承。ComboBox在选中其中一项显示到文本框里时,其实是执行了选中项数据源的ToString()方法。所以不能重载ExpandoObject的ToString()方法。所以这里自定义了一个轻量级的ExpandoObject类,继承于DynamicObject实现。

代码:

class dyData:DynamicObject
{
public dyData(string colName)
{
this.colName = colName;
}
//ToString时需要输出的属性
public string colName { get; set; }
//用于存储属性名和对应的值
Dictionary<string, object> data = new Dictionary<string, object>();
//绑定时获取对应属性的值
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return data.TryGetValue(binder.Name,out result);
}
//用于添加属性和对应的值
public void SetValue(string name, object value)
{
data.Add(name, value);
} //重写Tostring方法
public override string ToString()
{
try
{
return data[colName].ToString();
}
catch (Exception ex)
{
MessageBox.Show("找不到列名"+colName,"设置text要显示的项名时出错",MessageBoxButton.OK,MessageBoxImage.Error);
return null;
}
} }

  这样就实现了一个简易的ExpandoObject了。接下来遍历查询结果,通过SetValue动态创建对象的属性,添加进ObservableCollection<dynamic>数据集合,ComboBox直接数据绑定即可。

下载:demo

参考文献:

  lucene,你也会(7篇)——第一篇 快速入门

  使用Lucene.Net实现全文检索

  WPF地区选择控件(内附下载地址)

  

后记


  其实相同的功能我用查询数据库的方法,也实现过了,但是耗时每次都是100多毫秒。lucene估计有个缓存吧,速度会越来越快,而且经常被查寻的东西优先级别会提高,排在前面。

  以我的经验,写关于美工的文章比逻辑的获得的关注和推荐多得多。我也很想把通通玩Blend美工这个系列写下去,毕竟我大部分的粉丝都来源于这个系列。但是,最近几个月,都在纠结WF、WCF等等逻辑方面的,对美工没什么好的创意。  

  写博客图个什么?不就是作为一个平凡的码农,想要得到更多人的关注和认可,让我觉得自己其实和民工还是有点区别的。

  对了,我之前嵌在博客里的silverlight为什么都显示不出来了?xap文件我都是放在博客园的文件里的。求大神解答。

  

  

通通WPF随笔(1)——基于lucene.NET让ComboBox拥有强大的下拉联想功能的更多相关文章

  1. 通通WPF随笔(4)——通通手写输入法(基于Tablet pc实现)

    原文:通通WPF随笔(4)--通通手写输入法(基于Tablet pc实现) 从我在博客园写第一篇博客到现在已经有1年半了,我的第一篇博客写的就是手写识别,当时,客户需求在应用中加入手写输入功能,由于第 ...

  2. 通通WPF随笔(3)——艺术二维码素材生成器

    原文:通通WPF随笔(3)--艺术二维码素材生成器 最近公司让我开发一个条形码的生成控件,花了半天时间搞定觉得不过瘾,什么年代了该用二维码了吧.于是wiki了一下二维码的资料. 比较常见的就是QR码( ...

  3. 通通WPF随笔(2)——自己制作轻量级asp.net网站服务

    原文:通通WPF随笔(2)--自己制作轻量级asp.net网站服务 大学玩asp.net时就发现VS在Debug时会起一个web服务,这东西也太神奇了服务起得这么快,而相对于IIS又这么渺小. 前几个 ...

  4. 【selenium】基于python语言,如何用select选择下拉框

    在项目测试中遇到了下拉框选择的控件,来总结下如何使用select选择下拉框: 下图是Select类的初始化描述,意思是,给定元素是得是select类型,不是就抛异常.接下来给了例子:要操作这个sele ...

  5. 一款基于jQuery的联动Select下拉框

    今天我们要来分享一款很实用的jQuery插件,它是一个基于jQuery多级联动的省市地区Select下拉框,并且值得一提的是,这款联动下拉框是经过自定义美化过的,外观比浏览器自带的要漂亮许多.另外,这 ...

  6. WebGIS中兴趣点简单查询、基于Lucene分词查询的设计和实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 兴趣点查询是指:输入框中输入地名.人名等查询信息后,地图上可 ...

  7. 基于lucene实现自己的推荐引擎

    基于lucene实现自己的推荐引擎 推荐常用算法之-基于内容的推荐 推荐算法

  8. Apache Solr采用Java开发、基于Lucene的全文搜索服务器

    http://docs.spring.io/spring-data/solr/ 首先介绍一下solr: Apache Solr (读音: SOLer) 是一个开源.高性能.采用Java开发.基于Luc ...

  9. 基于lucene的案例开发:查询语句创建PackQuery

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44656141 http://www.llwjy.com/blogdetail/1 ...

随机推荐

  1. EChats+Ajax之柱状图的数据交互

    原文链接:https://blog.csdn.net/qq_37936542/article/details/79723710 一:下载 echarts.min.js 选择完整版进行下载,精简版和常用 ...

  2. [React] Normalize Events with Reacts Synthetic Event System

    Event handlers are passed an instance of SyntheticEvent in React. In this video we'll take a look at ...

  3. Android BlueDroid(一):BlueDroid概述

    关键词:bluedroid bluez作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!)欢迎指正错误.共同学习.共同进步!! 一.名词解释:(实用信息添加中--) BTI F: ...

  4. Bootstrap手机网站开发案例

    Bootstrap手机网站开发案例 一.总结 一句话总结:Bootstrap手机网站开发注意事项(3点):a.引入viewpoint声明,b.通过屏幕宽动态控制元素显隐 c.图片添加自适应 1.Boo ...

  5. 谷歌 AI 中国中心成立,人工智能势不可挡?

    昨日,谷歌在上海举办了一年一度的Google中国开发者大会.在本届大会上,谷歌云首席科学家李飞飞宣布了一个重磅消息,即在北京将成立谷歌AI中国中心.对于这个即将成立的AI中心谷歌寄予厚望,希望与中国本 ...

  6. Method and system for implementing mandatory file access control in native discretionary access control environments

    A method is provided for implementing a mandatory access control model in operating systems which na ...

  7. 数据集成工具Teiid Designer的环境搭建

    由于实验室项目要求的关系,看了些数据汇聚工具 Teiid 的相关知识.这里总结下 Teiid 的可视化配置工具 Teiid Designer 的部署过程. 背景知识 数据集成是把不同来源.格式.特点性 ...

  8. VS2017 Linux 上.NET Core调试

    调试Linux 上.NET Core Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Stud ...

  9. CSS动作

    5.过渡 tansition  (由一个状态过渡到另外一个状态的过程)             transition            过渡                 参数1:        ...

  10. [LeetCode]Word Break 特里

    意甲冠军:推断字符串给定的字符串是否构成词典. 来推断目标字符串相匹配整个字典.我们需要来推断目标字符串的每个前缀开始的下一场比赛,这需要匹配目标字符串的成功,所有前缀的枚举. class TrieN ...