在Web的应用方面有js的插件实现自动完成(或叫智能提示)功能,但在WinForm窗体应用方面就没那么好了。

TextBox控件本身是提供了一个自动提示功能,只要用上这三个属性:
AutoCompleteCustomSource:AutoCompleteSource 属性设置为CustomSource 时要使用的 StringCollection。
AutoCompleteMode:指示文本框的文本完成行为。
AutoCompleteSource:自动完成源,可以是 AutoCompleteSource 的枚举值之一。

就行了, 一个简单的示例如下
复制代码 代码如下:
textBox1.AutoCompleteCustomSource .AddRange(new string[] { "java","javascript","js","c#","c","c++" });
textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;

可是这种方式的不支持我们中文的简拼自动完成(如在文本框里输入"gz"就会出现"广州")。只好自己写一个支持简拼自动完成的控件了。
这是效果图
 
控件不太复杂,一个TextBox和一个ListBox。代码方面,用DataTable作数据源,每次在TextBox的值时,通过DataTable的Select方法,配上合适的表达式(如:{0} like '{1}%' and IsNull([{2}], ' ') <> ' ')来筛选出合适的备选文本内容,以下则是控件的代码:
复制代码 代码如下:
private TextBox _tb;
private ListBox _lb;
private DataTable _dt_datasource;
private bool _text_lock;
private string _general_text;//原始输入文本框的值
private bool _lb_kd_first_top;//listbox是否第一次到达顶部
private int _itemCount;

复制代码 代码如下:
/// <summary>
/// TextBox的Text属性,增加了_text_lock操作,放置触发TextChanged事件
/// </summary>
private string TextBoxText
{
get { return _tb.Text; }
set
{
_text_lock = true;
_tb.Text = value;
_text_lock = false;
}
}
/// <summary>
/// 显示在ListBox的字段名
/// </summary>
public string ValueName { get; set; }
/// <summary>
/// 用于匹配的字段名
/// </summary>
public string CodeName { get; set; }
/// <summary>
/// 显示提示项的数量
/// </summary>
public int ItemCount
{
get
{ return _itemCount; }
set
{
if (value <= 0)
_itemCount = 1;
else
_itemCount = value;
}
}
public DataTable DataSource
{
get { return _dt_datasource; }
set { _dt_datasource = value; }
}

复制代码 代码如下:
public AutoComplete()
{
InitialControls();
}

复制代码 代码如下:
void AutoComplete_Load(object sender, EventArgs e)
{
_tb.Width = this.Width;
_lb.Width = _tb.Width;
this.Height = _tb.Height-1;
}
void AutoComplete_LostFocus(object sender, EventArgs e)
{
_lb.Visible = false;
this.Height = _tb.Height-1;
}

复制代码 代码如下:
//列表框按键事件
void _lb_KeyDown(object sender, KeyEventArgs e)
{
if (_lb.Items.Count == 0 || !_lb.Visible) return;
if (!_lb_kd_first_top && ((e.KeyCode == Keys.Up && _lb.SelectedIndex == 0) || (e.KeyCode == Keys.Down && _lb.SelectedIndex == _lb.Items.Count)))
{
_lb.SelectedIndex = -1;
TextBoxText = _general_text;
}
else
{
TextBoxText = ((DataRowView)_lb.SelectedItem)[ValueName].ToString();
_lb_kd_first_top = _lb.SelectedIndex != 0;
}
if (e.KeyCode == Keys.Enter && _lb.SelectedIndex != -1)
{
_lb.Visible = false;
this.Height = _tb.Height;
_tb.Focus();
}
}
//列表鼠标单击事件
void _lb_Click(object sender, EventArgs e)
{
if (_lb.SelectedIndex != -1)
{
TextBoxText = ((DataRowView)_lb.SelectedItem)[ValueName].ToString();
}
_lb.Visible = false;
_tb.Focus();
this.Height = _tb.Height;
}

复制代码 代码如下:
//文本框按键事件
void _tb_KeyDown(object sender, KeyEventArgs e)
{
if (_lb.Items.Count == 0||!_lb.Visible) return;
bool _is_set = false;
if (e.KeyCode == Keys.Up)
{
if (_lb.SelectedIndex <= 0)
{
_lb.SelectedIndex = -1;
TextBoxText = _general_text;
}
else
{
_lb.SelectedIndex--;
_is_set = true;
}
}
else if (e.KeyCode == Keys.Down)
{
if (_lb.SelectedIndex == _lb.Items.Count - 1)
{
_lb.SelectedIndex = 0;
_lb.SelectedIndex = -1;
TextBoxText = _general_text;
}
else
{
_lb.SelectedIndex++;
_is_set = true;
}
}
else if (e.KeyCode == Keys.Enter)
{
_lb.Visible = false;
this.Height = _tb.Height;
_is_set = _lb.SelectedIndex != -1;
}
_lb_kd_first_top = _lb.SelectedIndex != 0;
if (_is_set)
{
_text_lock = true;
_tb.Text = ((DataRowView)_lb.SelectedItem)[ValueName].ToString();
_tb.SelectionStart = _tb.Text.Length + 10;
_tb.SelectionLength = 0;
_text_lock = false;
}
}
//文本框文本变更事件
void _tb_TextChanged(object sender, EventArgs e)
{
if (_text_lock) return;
_general_text = _tb.Text;
_lb.Visible = true;
_lb.Height = _lb.ItemHeight * (_itemCount+1);
this.BringToFront();
_lb.BringToFront();
this.Height = _tb.Height + _lb.Height;
DataTable temp_table = _dt_datasource.Clone();
string filtStr = FormatStr(_tb.Text);
DataRow [] rows = _dt_datasource.Select(string.Format(GetFilterStr(),CodeName,filtStr,_lb.DisplayMember));
for (int i = 0; i < rows.Length&&i<_itemCount; i++)
{
temp_table.Rows.Add(rows[i].ItemArray);
}
_lb.DataSource = temp_table;
if (_lb.Items.Count > 0) _lb.SelectedItem = _lb.Items[0];
}

复制代码 代码如下:
/// <summary>
/// 初始化控件
/// </summary>
private void InitialControls()
{
_lb_kd_first_top = true;
_tb = new TextBox();
_tb.Location = new Point(0, 0);
_tb.Margin = new System.Windows.Forms.Padding(0);
_tb.Width = this.Width;
_tb.TextChanged += new EventHandler(_tb_TextChanged);
_tb.KeyUp += new KeyEventHandler(_tb_KeyDown);
_lb = new ListBox();
_lb.Visible = false;
_lb.Width = _tb.Width;
_lb.Margin = new System.Windows.Forms.Padding(0);
_lb.DisplayMember = ValueName;
_lb.SelectionMode = SelectionMode.One;
_lb.Location = new Point(0, _tb.Height);
_lb.KeyUp += new KeyEventHandler(_lb_KeyDown);
_lb.Click += new EventHandler(_lb_Click);
this.Controls.Add(_tb);
this.Controls.Add(_lb);
this.Height = _tb.Height - 1;
this.LostFocus += new EventHandler(AutoComplete_LostFocus);
this.Leave += new EventHandler(AutoComplete_LostFocus);
this.Load += new EventHandler(AutoComplete_Load);
}
/// <summary>
/// 获取过滤格式字符串
/// </summary>
/// <returns></returns>
private string GetFilterStr()
{
//未过滤注入的字符 ' ] %任意 *任意
string filter = " {0} like '{1}%' and IsNull([{2}], ' ') <> ' ' ";
if (_dt_datasource.Rows[0][CodeName].ToString().LastIndexOf(';') > -1)
filter = " {0} like '%;{1}%' and IsNull([{2}],' ') <> ' ' ";
return filter;
}
/// <summary>
/// 过滤字符串中一些可能造成出错的字符
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private string FormatStr(string str)
{
if (string.IsNullOrEmpty(str)) return string.Empty;
str = str.Replace("[", "[[]").Replace("%", "[%]").Replace("*", "[*]").Replace("'", "''");
if (CodeName == "code") str = str.Replace(" ", "");
return str;
}

下面是使用控件的例子
复制代码 代码如下:
class Common
{
/// <summary>
/// 生成测试数据源
/// </summary>
public static DataTable CreateTestDataSoucre
{
get
{
List<KeyValuePair<string, string>> source = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string,string>("张三",";zs;张三;"),
new KeyValuePair<string,string>("李四",";li;李四;"),
new KeyValuePair<string,string>("王五",";ww;王五;"),
new KeyValuePair<string,string>("赵六",";zl;赵六;"),
new KeyValuePair<string,string>("洗刷",";cs;csharp;c#;洗刷;"),
new KeyValuePair<string,string>("爪哇",";java;爪哇;"),
new KeyValuePair<string,string>("java",";java;"),
new KeyValuePair<string,string>("c#",";c#;cs;csharp;"),
new KeyValuePair<string,string>("javascript",";javascript;js;")
};
DataTable table = new DataTable();
table.Columns.Add("id");
table.Columns.Add("name");
table.Columns.Add("code");
for (int i = 0; i < source.Count; i++)
{
DataRow row = table.Rows.Add();
row["id"] = i;
row["name"] = source[i].Key;
row["code"] = source[i].Value;
}
return table;
}
}
}
//.............
AutoComplete ac=new AutoComplete();
ac.ValueName = "name";
ac.CodeName = "code";
ac.DataSource= Common.CreateTestDataSoucre;
ac.ItemCount= 5;

详细出处参考:http://www.jb51.net/article/33386.htm

WinForm 自动完成控件实例代码简析的更多相关文章

  1. winform 自定义自动完成控件

    做过前端的朋友肯定很清楚自动完成控件,很多优秀的前端框架都会带有自动完成控件,同样的,winform也有,在我们的TextBox和ComboBox中,只需要设置AutoCompleteSource属性 ...

  2. Atitit.auto complete 自动完成控件的实现总结

    Atitit.auto complete  自动完成控件的实现总结 1. 框架选型 1 2. 自动完成控件的ioc设置 1 3. Liger  自动完成控件问题 1 4. 官网上的code有问题,不能 ...

  3. Silverlight动态生成控件实例

    刚学习Silverlight,做了一个动态创建控件的实例 实现结果:根据已有的控件类名称,得到控件的实例化对象 实现思路1:就是定义一个模板文件,将类名做为参数,在silverlight中使用Srea ...

  4. c#依参数自动生成控件

    很多系统都带有自定义报表的功能,而此功能都需依参数自动生成控件,举例如下: 如上图,一条查询语句当中,包含了3个参数,其中两个是日期型(使用:DATE!进行标识),一个是字符型(使用:进行标识),要生 ...

  5. c#字符串加载wpf控件模板代码 - 简书

    原文:c#字符串加载wpf控件模板代码 - 简书 ResourceManager resManagerA = new ResourceManager("cn.qssq666.Properti ...

  6. OpenStack之虚机冷迁移代码简析

    OpenStack之虚机冷迁移代码简析 前不久我们看了openstack的热迁移代码,并进行了简单的分析.真的,很简单的分析.现在天气凉了,为了应时令,再简析下虚机冷迁移的代码. 还是老样子,前端的H ...

  7. 嵌套在母版页中的repeater自动生成控件ID

    注:如果直接在后台通过e.Item.FindControl()方法直接找控件,然后再通过对其ID赋值,在编译之后会出现“母版页名称_ID“类似的很长的ID值(详情点击) 解决方法:<asp:Co ...

  8. c# winform动态生成控件与获取动态控件输入的值

    差不多有2年没有写winform程序,一直都是写bs.最近项目需要,又开始着手写一个小功能的winform程序,需要动态获取xml文件的节点个数,生成跟节点个数一样的textbox, 最后还要获取操作 ...

  9. [转]winform 自动伸缩控件xpandercontrols 使用说明

    链接地址:http://blog.sina.com.cn/s/blog_b5b004920101f5h3.html

随机推荐

  1. [转] 使用moment.js轻松管理日期和时间

    当前时间:moment().format('YYYY-MM-DD HH:mm:ss'); 2017-03-01 16:30:12 今天是星期几:moment().format('d'); 3 Unix ...

  2. element-ui的rules中正则表达式

    <template> <el-form :model="unuseForm" label-position="top" :rules=&quo ...

  3. 【LOJ】#6436. 「PKUSC2018」神仙的游戏

    题解 感觉智商为0啊QAQ 显然对于一个长度为\(len\)的border,每个点同余\(n - len\)的部分必然相等 那么我们求一个\(f[a]\)数组,如果存在\(s[x] = 0\)且\(s ...

  4. CSS------ul与div如何排成一行

    如图: 代码:(需要给div的float属性设置为left) <div style="margin-top:10px"> <div style="flo ...

  5. java List/ArrayList 解惑

    导读:祖传挖坟派学习方法(宝儿姐友情支持) 第一部分  List简介 第二部分  何为ArrayList 第三部分  代码示例 第四部分  吹牛 如果你急需想搞清楚一些问题可以先看这里的总结 再后续看 ...

  6. 8.9 正睿暑期集训营 Day6

    目录 2018.8.9 正睿暑期集训营 Day6 A 萌新拆塔(状压DP) B 奇迹暖暖 C 风花雪月(DP) 考试代码 A B C 2018.8.9 正睿暑期集训营 Day6 时间:2.5h(实际) ...

  7. JavaScript学习历程和心得体验

    一.前言 在过去,JavaScript只是被用来做一些简单的网页效果,比如表单验证.浮动广告等,所以那时候JavaScript并没有受到重视.自从AJAX开始流行后,人们发现利用JavaScript可 ...

  8. 使用 IntraWeb (4) - 页面布局之 TIWRegion

    TIWRegion 是容器, 首先布局好它(们). 在空白窗体上添加 4 个 TIWRegion, 然后: uses System.UITypes; //为使用 Anchors 属性 {下面代码中的设 ...

  9. cmsis dap interface firmware

    cmsis dap interface firmware The source code of the mbed HDK (tools + libraries) is available in thi ...

  10. C# webrequest 抓取数据时,多个域Cookie的问题

    最近研究了下如何抓取为知笔记的内容,在抓取笔记里的图片内容时,老是提示403错误,用Chorme的开发者工具看了下: 这里的Cookie来自两个域,估计为知那边是验证了token(登录后才能获取到to ...