【问题标题】:How to create an Auto-complete combo-box or text box to filter text containing a string如何创建自动完成组合框或文本框来过滤包含字符串的文本
【发布时间】:2011-05-17 21:54:31
【问题描述】:

如何创建基于字符串过滤文本的自动完成组合框或文本框?

例如:如果我在 TextBox 中键入“a”,我只能看到所有包含“a”的字符串。

【问题讨论】:

  • 网络表单?窗体? MVC? WPF?
  • 您使用的是哪个版本的框架?您可以访问 LINQ 吗?

标签: c# winforms autocomplete


【解决方案1】:

如果您的意思是显示建议,那么当您在所选 IDE 中选择了 TextBox 时,更改属性很简单:

图片中显示的选项允许您更改文本框中自动完成文本的规则以及建议的来源。 (Visual Studio 2010)

您可以前往以下链接了解更多有关 TextBox 控件的信息。

MSDN Text Box Control

【讨论】:

    【解决方案2】:

    Windows 窗体的自动完成实现使用 Shell 的自动完成对象,在 Windows Vista 之前只能进行“BeginWith”匹配。 如果您可以要求您的用户升级到 Windows Vista,您可以use IAutoComplete2::SetOptions 指定 ACO_NOPREFIXFILTERING。否则恐怕你需要write your own

    【讨论】:

    • 在使用默认的 TextBox 和 ComboBox 实现时如何做到这一点?
    • 你不能。无法为此任务自定义 Windows 窗体实现。
    • 感谢您的确认,根据您链接的实现,我有点想通了。你能告诉我为什么你所做的实现不能正确处理上下键吗?如果我在您的实现中使用 ACO_NOPREFIXFILTERING 标志,则向上和向下键将分别选择最后一项和第一项,然后关闭自动完成窗口。不显示选择突出显示。
    • 这可能与重置候选列表有关。如果您只想要一个常规的自动完成功能(在您输入时不刷新候选列表),您可以在 TextChanged 事件中注释掉代码。
    【解决方案3】:

    这是我如何自动完成组合下拉框中的特定值。

        void comboBox_Leave(object sender, EventArgs e)
        {
           ComboBox cbo = (sender as ComboBox);
            if (cbo.Text.Length > 0)
            {
                Int32 rowIndex = cbo.FindString(cbo.Text.Trim());
                if (rowIndex != -1)
                {
                    cbo.SelectedIndex = rowIndex;
                }
                else
                {
                    cbo.SelectedIndex = -1;
                }
            }
            else
            {
                cbo.SelectedIndex = -1;
            }
    
        }
    

    【讨论】:

      【解决方案4】:

      这会根据用户输入过滤结果。针对大型列表进行优化,填充您自己的数据和错误处理留待您完成:

      public partial class Form1 : Form
          {
      
              List<String> data;
              ListView lst = new ListView();
              TextBox txt = new TextBox();
      
              public Form1()
              {
                  InitializeComponent();
                  data = new List<string>("Lorem ipsum dolor sit amet consectetur adipiscing elit Suspendisse vel".Split());
              }
      
              private void Form1_Load(object sender, EventArgs e)
              {
                  this.Controls.Add(txt);
                  lst.Top = 20;
                  txt.TextChanged += new EventHandler(txt_TextChanged);
                  lst.View = View.List;
                  this.Controls.Add(lst);
                  list_items("");
              }
      
              void txt_TextChanged(object sender, EventArgs e)
              {
                  list_items(txt.Text);
              }
      
              void list_items(string filter)
              {
                  lst.Items.Clear();
                  List<string> results = (from d in data where d.Contains(filter) select d).ToList();
                  foreach (string s in results)
                  {
                      lst.Items.Add(s);
                  }
              }
          }
      

      要让组合框自动完成,请设置 AutoCompleteSource 和 AutoCompleteMode 属性:

      cbo.AutoCompleteSource = AutoCompleteSource.ListItems;
      cbo.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
      

      ListItems 源告诉组合使用它的项目集合作为自动完成源。

      【讨论】:

      • 在此方法中只显示以“a”开头的文本,而不显示包含“a”的文本
      • 这需要自定义滚动解决方案,因为默认情况下不内置此功能。
      【解决方案5】:

      我知道这是一个老话题,但我也非常努力地寻找 C# 自动完成过滤的解决方案,但找不到任何解决方案,所以我想出了自己的简单方法,所以我将分享给那些人谁可能认为它有用并想在他们的项目中使用。它不使用控件的自动完成功能。它所做的只是简单地获取从组合框输入的文本,在源中搜索它,然后仅将源​​中匹配的文本显示为组合框的新源。我在组合框的KeyUp 事件中实现了它。

      假设(实际上,当我想要自动完成时,几乎所有情况下我都会这样做)我们有一个全局分配的 DataTable,称为 dt_source 作为组合框的源,它有两列:id(int) 和 name (字符串)。

      DataTable dt_source = new DataTable("table");
      dt_source.Columns.Add("id", typeof(int));
      dt_source.Columns.Add("name", typeof(string));
      

      这就是我的 KeyUp 方法的样子:

      private void cmb_box_KeyUp(object sender, KeyEventArgs e)
      {
        string srch = cmb_box.Text;
        string srch_str = "ABackCDeleteEFGHIJKLMNOPQRSpaceTUVWXYZD1D2D3D4D5D6D7D8D9D0"; 
        if (srch_str.IndexOf(e.KeyCode.ToString()) >= 0)
        {
          cmb_box.DisplayMember = "name"; // we want name list in the datatable to be shown
          cmb_box.ValueMember = "id"; // we want id field in the datatable to be the value
          DataView dv_source = new DataView(dt_source);  // make a DataView from DataTable so ...
          dv_source.RowFilter = "name LIKE '%"+ srch +"%'"; // ... we can filter it
          cmb_box.DataSource = dv_source; // append this DataView as a new source to the combobox         
          /* The 3 lines below is the tricky part. If you repopulate a combobox, the first
             item in it will be automatically selected so let's unselect it*/
          cmb_box.SelectedIndex = -1; // unselection
          /* Again when a combobox repopulated the text region will be reset but we have the
             srch variable to rewrite what's written before */
          cmb_box.Text = srch;
          /* And since we're rewriting the text region let's make the cursor appear at the
             end of the text - assuming 100 chars is enough*/
          cmb_box.Select(100,0);
          cmb_box.DroppedDown = true; // Showing the dropdownlist
         }
      }
      

      【讨论】:

        【解决方案6】:

        我认为您最好的选择是覆盖 OnKeyDown(KeyEventArgs e) 事件,并使用该值过滤 ComboBox.AutoCompleteCustomSource。然后如上所述,将 AutoCompleteSource 更改为 AutoCompleteSource.ListItems。

        【讨论】:

        • 处理OnKeyDown 通常被认为是最糟糕的选择。除其他外,它将无法处理粘贴到编辑控件中的输入(例如右键单击 -> 粘贴)。
        • 对于组合框参考这个stackoverflow.com/questions/11780558/…
        猜你喜欢
        • 2016-01-20
        • 1970-01-01
        • 2014-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-30
        • 2010-10-05
        相关资源
        最近更新 更多