在一个项目总ComboBox中有很多项目,用户查找非常麻烦,系统自带的快速定位是匹配首字母,使用起来非常不方便。网上找了很多,都是基于Items.Add()的方式,这种方式不支持数据源的键值对应,只有自己写一个了,看看效果先!
看起来不错,允许从任意位置匹配项目,而且不需要是连续的,最重要的是支持汉语拼音首字母匹配。
实现原理:将数据源备份到变量DataSource2,在TextChanged事件中循环DataSource2,找到匹配后添加到临时表,循环结束后将临时表绑定到DataSource。注意,在绑定中不要修改DataSource,这样速度无法忍受。
该方法使用DataSource2作为原数据源的引用,DataSource只是过滤后的副本,好了,废话少说,看代码
using System;
using System.Text;
namespace Socg
{
public class ComboBox:System.Windows.Forms.ComboBox
{
#region public bool CleverFilter----智能过滤
/// <summary>
/// 智能过滤时使用
/// </summary>
public object DataSource2=null;
/// <summary>
/// 避免绑定数据源后导致的递归调用
/// </summary>
private bool lock_文本改变=false;
//如果中下拉菜单中选择项目,事件顺序为SelectionChangeCommitted->TextChanged->SelectedValue
private bool lock_点选列表项=false;
private bool cleverFilter=false;
/// <summary>
/// 使ComboBox有智能过滤功能。在输入文本时会自动根据输入的内容进行匹配。这种匹配不需从首字母开始,且可以“间隔匹配”,还支持拼音首字母匹配。
/// 例如:“以太网交换机”用“以交换”、“y交换”、“以jh”、“y交h”可以匹配(包括空字符串),用“已交换”,“以换交”不能匹配。
/// 实现方法是增加变量“DataSource2”来存储原始数据源。输入字符后搜索“DataSource2”,找到匹配后添加到临时DataTable,最后将临时DataTable赋值到DataSource属性达到过滤效果。
/// 需要注意的是从DataSource的到的数据源已经不是原始的数据源。回收时需要注意数据源副本的回收。为此,代码规定了启用“智能过滤”前必须手动设置DataSource2。停用“DataSource2”时必须先使DataSource2=null,否则会抛出异常。
/// </summary>
public bool CleverFilter
{
get
{
return cleverFilter;
}
set
{
if(CleverFilter!=value)
{
cleverFilter=value;
if(value==true)
{
if(DataSource2==null)
{
throw new Exception("启用“智能过滤”时必须主动设置DataSource2=DataSource,设置成功之后DataSource将变为副本,真正原始的数据源在DataSource2");
}
this.TextChanged+=new EventHandler(ComboBox_TextChanged);
this.SelectedValueChanged+=new EventHandler(ComboBox_SelectedValueChanged);
this.SelectionChangeCommitted+=new EventHandler(ComboBox_SelectionChangeCommitted);
}
else
{
if(DataSource2!=null)
{
throw new Exception("取消“智能过滤”时必须主动设置DataSource2为null,它是真正的数据源,这是应将DataSource=DataSource2");
}
this.TextChanged-=new EventHandler(ComboBox_TextChanged);
this.SelectedValueChanged-=new EventHandler(ComboBox_SelectedValueChanged);
this.SelectionChangeCommitted-=new EventHandler(ComboBox_SelectionChangeCommitted);
}
}
}
}
#endregion
void ComboBox_SelectionChangeCommitted(object sender,EventArgs e)
{
lock_点选列表项=true;
}
void Co