如何在 Winforms 桌面应用程序中制作自动完成文本框
Posted
技术标签:
【中文标题】如何在 Winforms 桌面应用程序中制作自动完成文本框【英文标题】:How to make an auto-complete textbox in a winforms desktop application 【发布时间】:2011-06-05 12:29:04 【问题描述】:我有一个单词列表。该列表包含大约 100-200 个文本字符串(实际上是地铁站的名称)。
我想制作一个自动完成的文本框。例如,用户按下“N”字母,然后出现一个(结束)适当的选项(只有一个选项)。必须选择结局。
怎么做?
PS1:我猜,有一个带有如下属性的文本框控件:
List<string> AppropriateOptions/* ... */
PS2:对不起我的英语。如果你不明白 -> 问我,我会尽力解释!
【问题讨论】:
【参考方案1】:以防万一@leniel 的链接失效,这里有一些代码可以解决问题:
AutoCompleteStringCollection allowedTypes = new AutoCompleteStringCollection();
allowedTypes.AddRange(yourArrayOfSuggestions);
txtType.AutoCompleteCustomSource = allowedTypes;
txtType.AutoCompleteMode = AutoCompleteMode.Suggest;
txtType.AutoCompleteSource = AutoCompleteSource.CustomSource;
【讨论】:
谢谢乔尔,它对我有用。我们可以用向上和向下箭头键选择建议文本吗?我试过但它不允许我。 @rakesh 我已经有一段时间没有在 winforms 上工作了,我不记得是“标准”功能还是需要额外的努力。对不起 感谢您提供要点而不是仅提供链接的答案。【参考方案2】:使用组合框而不是文本框。以下示例将自动完成,匹配任何一段文本,而不仅仅是起始字母。
这应该是一个完整的表格,只需添加您自己的数据源,以及数据源列名。 :-)
using System;
using System.Data;
using System.Windows.Forms;
public partial class frmTestAutocomplete : Form
private DataTable maoCompleteList;
private const string MC_DISPLAY_COL = "name";
private const string MC_ID_COL = "id";
public frmTestAutocomplete()
InitializeComponent();
private void frmTestAutocomplete_Load(object sender, EventArgs e)
maoCompleteList = oData.PurificationRuns;
maoCompleteList.CaseSensitive = false; //turn off case sensitivity for searching
testCombo.DisplayMember = MC_DISPLAY_COL;
testCombo.ValueMember = MC_ID_COL;
testCombo.DataSource = GetDataTableFromDatabase();
testCombo.SelectedIndexChanged += testCombo_SelectedIndexChanged;
testCombo.KeyUp += testCombo_KeyUp;
private void testCombo_KeyUp(object sender, KeyEventArgs e)
//use keyUp event, as text changed traps too many other evengts.
ComboBox oBox = (ComboBox)sender;
string sBoxText = oBox.Text;
DataRow[] oFilteredRows = maoCompleteList.Select(MC_DISPLAY_COL + " Like '%" + sBoxText + "%'");
DataTable oFilteredDT = oFilteredRows.Length > 0
? oFilteredRows.CopyToDataTable()
: maoCompleteList;
//NOW THAT WE HAVE OUR FILTERED LIST, WE NEED TO RE-BIND IT WIHOUT CHANGING THE TEXT IN THE ComboBox.
//1).UNREGISTER THE SELECTED EVENT BEFORE RE-BINDING, b/c IT TRIGGERS ON BIND.
testCombo.SelectedIndexChanged -= testCombo_SelectedIndexChanged; //don't select on typing.
oBox.DataSource = oFilteredDT; //2).rebind to filtered list.
testCombo.SelectedIndexChanged += testCombo_SelectedIndexChanged;
//3).show the user the new filtered list.
oBox.DroppedDown = true; //this will overwrite the text in the ComboBox, so 4&5 put it back.
//4).binding data source erases text, so now we need to put the user's text back,
oBox.Text = sBoxText;
oBox.SelectionStart = sBoxText.Length; //5). need to put the user's cursor back where it was.
private void testCombo_SelectedIndexChanged(object sender, EventArgs e)
ComboBox oBox = (ComboBox)sender;
if (oBox.SelectedValue != null)
MessageBox.Show(string.Format(@"Item #0 was selected.", oBox.SelectedValue));
//=====================================================================================================
// code from frmTestAutocomplete.Designer.cs
//=====================================================================================================
partial class frmTestAutocomplete
/// <summary>
/// Required designer variable.
/// </summary>
private readonly System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
this.testCombo = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// testCombo
//
this.testCombo.FormattingEnabled = true;
this.testCombo.Location = new System.Drawing.Point(27, 51);
this.testCombo.Name = "testCombo";
this.testCombo.Size = new System.Drawing.Size(224, 21);
this.testCombo.TabIndex = 0;
//
// frmTestAutocomplete
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.testCombo);
this.Name = "frmTestAutocomplete";
this.Text = "frmTestAutocomplete";
this.Load += new System.EventHandler(this.frmTestAutocomplete_Load);
this.ResumeLayout(false);
#endregion
private System.Windows.Forms.ComboBox testCombo;
【讨论】:
【参考方案3】:Leniel 的答案链接在 vb.net,感谢 Joel 的输入。提供我的代码以使其更明确:
private void InitializeTextBox()
AutoCompleteStringCollection allowedStatorTypes = new AutoCompleteStringCollection();
var allstatortypes = StatorTypeDAL.LoadList<List<StatorType>>().OrderBy(x => x.Name).Select(x => x.Name).Distinct().ToList();
if (allstatortypes != null && allstatortypes.Count > 0)
foreach (string item in allstatortypes)
allowedStatorTypes.Add(item);
txtStatorTypes.AutoCompleteMode = AutoCompleteMode.Suggest;
txtStatorTypes.AutoCompleteSource = AutoCompleteSource.CustomSource;
txtStatorTypes.AutoCompleteCustomSource = allowedStatorTypes;
【讨论】:
【参考方案4】:使用组合框,设置其数据源或提供硬编码条目,但设置以下属性:
AutoCompleteMode = Suggest;
AutoCompleteSource = ListItems;
【讨论】:
【参考方案5】:您希望将TextBox.AutoCompleteSource
设置为CustomSource
,然后将所有字符串添加到其AutoCompleteCustomSource
属性,即StringCollection
。那你应该很高兴了。
【讨论】:
【参考方案6】:我想补充一点,TextBox 的标准自动完成功能只能从字符串的开头开始工作,所以如果你点击 N,只会找到以 N 开头的字符串。如果您想要更好的东西,您必须使用一些不同的控件或自己实现行为(即使用一些计时器对 TextChanged 事件做出反应以延迟执行,而不是使用 IndexOf(inputString) 过滤您的令牌列表搜索,然后将您的 AutoCompleteSource 设置为过滤后的列表。
【讨论】:
以上是关于如何在 Winforms 桌面应用程序中制作自动完成文本框的主要内容,如果未能解决你的问题,请参考以下文章
连接到 SQL Server 数据库 C#-WinForms
为啥 WPF 中的鼠标位置不正确,而缩放桌面上的 Winforms 则不正确?
如何在每个使用桌面分辨率的右下角放置一个窗口(Winforms)