【问题标题】:How to make an auto-complete textbox in a winforms desktop application如何在 Winforms 桌面应用程序中制作自动完成文本框
【发布时间】:2011-06-05 12:29:04
【问题描述】:

我有一个单词列表。该列表包含大约 100-200 个文本字符串(实际上是地铁站的名称)。

我想制作一个自动完成的文本框。例如,用户按下“N”字母,然后出现一个(结束)适当的选项(只有一个选项)。必须选择结局。

怎么做?

PS1:我猜,有一个带有如下属性的文本框控件:

List<string> AppropriateOptions{/* ... */}

PS2:对不起我的英语。如果你不明白 -> 问我,我会尽力解释!

【问题讨论】:

    标签: c# winforms autocomplete textbox desktop-application


    【解决方案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 设置为过滤后的列表。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-01-23
              • 2011-04-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-01
              相关资源
              最近更新 更多