如何在列表框中实现增量搜索?

6

我希望在与Listbox绑定的键值对列表上实现增量搜索。

如果有三个值(AAB,AAC,AAD),那么用户应该能够在可用列表框中选择一个项目并输入“AAC”,该项目应该被突出显示并聚焦。它还应该以增量方式进行。

处理此问题的最佳方法是什么?


我不知道如何处理这个问题。每当用户输入一个“char”时,需要在列表中搜索该项并将其突出显示... 不知道要在哪个事件(在listbox上)处理... - Dhanapal
4个回答

7
在 KeyChar 事件中添加一个处理程序(在我的情况下,列表框的名称为 lbxFieldNames):
private void lbxFieldNames_KeyPress(object sender, KeyPressEventArgs e)
{
  IncrementalSearch(e.KeyChar);
  e.Handled = true;
}

重要提示:您需要添加 e.Handled = true;,因为列表框默认实现了“转到以此字符开头的第一项”搜索;我花了一些时间才弄清楚为什么我的代码无法正常工作。

IncrementalSearch 方法如下:

private void IncrementalSearch(char ch)
{
  if (DateTime.Now - lastKeyPressTime > new TimeSpan(0, 0, 1))
    searchString = ch.ToString();
  else
    searchString += ch;
  lastKeyPressTime = DateTime.Now;

  var item = lbxFieldNames
    .Items
    .Cast<string>()
    .Where(it => it.StartsWith(searchString, true, CultureInfo.InvariantCulture))
    .FirstOrDefault();
  if (item == null)
    return;

  var index = lbxFieldNames.Items.IndexOf(item);
  if (index < 0)
    return;

  lbxFieldNames.SelectedIndex = index;
}

我实现的时间限制是一秒钟,但您可以通过修改if语句中的TimeSpan来更改它。
最后,您需要声明。
private string searchString;
private DateTime lastKeyPressTime;

4
如果我正确理解您的问题,似乎您希望用户能够开始输入并提供建议。
您可以使用ComboBox(而不是ListBox):
1. 将DataSource设置为KeyValuePairs列表, 2. 将ValueMember设置为“Key”,将DisplayMember设置为“Value”, 3. 将AutoCompleteMode设置为SuggestAppend, 4. 将AutoCompleteSource设置为ListItems。

不允许使用组合框,只能使用列表框!! - Dhanapal

2
您可以使用TextChanged事件,在用户输入字符时触发它,您还可以与此同时使用listbox事件DataSourceChanged,以悬停在特定项或其他您想要的内容上。
我会给您举个例子:
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        listBox1.DataSource = GetProducts(textBox1.Text);
        listBox1.ValueMember = "Id";
        listBox1.DisplayMember = "Name";
    }

    List<Product> GetProducts(string keyword)
    {
        IQueryable q = from p in db.GetTable<Product>()
                       where p.Name.Contains(keyword)
                       select p;
        List<Product> products = q.ToList<Product>();
        return products;
    }

每当用户开始输入字符时,getproducts方法就会执行并填充列表框,并默认悬停在列表中的第一项。您还可以使用列表框事件DataSourceChanged来处理它,以便进行其他操作。
另外还有一种有趣的方法,即:TextBox.AutoCompleteCustomSource属性
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
AutoCompleteStringCollection stringCollection = 
    new AutoCompleteStringCollection();
textBox1.AutoCompleteCustomSource = stringCollection;

这个列表只能接受 string[],所以您可以从数据源中获取它们,然后当 textbox 的文本更改时,从已填入文本框自动完成自定义源的数据源中添加相似的单词。

private void textBox1_TextChanged(object sender, EventArgs e)
    {
        listBox1.Items.Clear();
        if (textBox1.Text.Length == 0)
        {
            listbox1.Visible = false;
            return;
        }

        foreach (String keyword in textBox1.AutoCompleteCustomSource)
        {
            if (keyword.Contains(textBox1.Text))
            {
                listBox1.Items.Add(keyword);
                listBox1.Visible = true;
            }
        }

    }

添加另一个事件ListBoxSelectedindexchanged,将所选文本添加到文本框中。


1
也许你可以在用户正在输入搜索内容的控件上(我猜是一个TextBox)添加一个TextChanged事件。在这个事件中,你可以循环遍历所有项,以查找与用户输入的单词最相符的那一项。

不,这不是文本框,他从列表中选择任何项目并“开始”输入他要搜索和突出显示的单词... - Dhanapal
@Dhana 对不起,我误解了你的上下文。 - Otiel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接