WinForm 自动完成控件实例代码简析
WinForm 自动完成控件实例代码简析
发布时间:2017-01-07 来源:查字典编辑
摘要:在Web的应用方面有js的插件实现自动完成(或叫智能提示)功能,但在WinForm窗体应用方面就没那么好了。TextBox控件本身是提供了一...

在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"就会出现"广州")。只好自己写一个支持简拼自动完成的控件了。

这是效果图

WinForm 自动完成控件实例代码简析1

控件不太复杂,一个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;

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新C#教程学习
热门C#教程学习
编程开发子分类