[英]How to make an auto-complete textbox in a winforms desktop application
我有一個詞表。 該列表包含大約100-200個文本字符串(實際上是地鐵站的名稱)。
我想制作一個自動完成的文本框。 例如,用戶按“ N”字母,然后出現一個(結束)適當的選項(僅一個選項)。 必須選擇結尾。
怎么做?
PS1:我猜想,有一個帶有屬性的文本框控件,如下所示:
List<string> AppropriateOptions{/* ... */}
PS2:對不起,我的英語。 如果您聽不懂->問我,我會盡力解釋!
以防萬一@leniel的鏈接斷開,下面的代碼可以解決問題:
AutoCompleteStringCollection allowedTypes = new AutoCompleteStringCollection();
allowedTypes.AddRange(yourArrayOfSuggestions);
txtType.AutoCompleteCustomSource = allowedTypes;
txtType.AutoCompleteMode = AutoCompleteMode.Suggest;
txtType.AutoCompleteSource = AutoCompleteSource.CustomSource;
使用組合框而不是文本框。 下面的示例將自動完成,匹配文本的任何部分,而不僅僅是起始字母。
這應該是一個完整的表格,只需添加您自己的數據源和數據源列名。 :-)
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;
}
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;
}
我想補充一下,TextBox的標准自動完成功能僅從字符串的開頭開始起作用,因此,如果您按N,則只會找到以N開頭的字符串。 如果您想要更好的東西,則必須使用一些不同的控件或自己實現行為(即,使用一些計時器對TextChanged Event做出反應以延遲執行),而不是使用IndexOf(inputString)過濾令牌列表搜索,然后將AutoCompleteSource設置為過濾后的列表。
您想要將TextBox.AutoCompleteSource
設置為CustomSource
,然后將所有字符串添加到其AutoCompleteCustomSource
屬性(即StringCollection
。 那你應該很好。
使用組合框,設置其數據源或提供硬編碼的條目,但設置以下屬性:
AutoCompleteMode = Suggest;
AutoCompleteSource = ListItems;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.