【问题标题】:Searching in a listBox using backgroundWorker使用 backgroundWorker 在列表框中搜索
【发布时间】:2017-10-04 17:33:46
【问题描述】:

这是一个 C# - WinForm 问题: 我正在尝试在列表框中进行搜索。只有一个列表框包含一些项目。在程序加载时,listBox 中的所有项目都被复制到名为“tempList”的字符串类型列表中。 还有一个文本框。当用户开始在 TextBox 中键入时,使用 Clear() 方法清除列表框。之后,将使用 foreach 块在 tempList 中搜索文本框中的单词。每个匹配项都将添加到 listBox 并显示给用户。 我想出了这段代码:

private void textBox1_TextChanged(object sender, EventArgs e)
    {
        listBox1.Items.Clear();
        foreach (string item in tempList)
        {
            if (item.ToLower().Contains(textBox1.Text.ToLower()))
            {
                listBox1.Items.Add(item);
            }
        }
    }

问题是,当用户开始在文本框中输入第一个字符时,用户界面会中断,用户必须等到完成对那个字符的搜索,然后他们可以再次键入,并且每个字符都会发生这种情况。为了解决这个问题,我发现我可以使用 backgroundWorker。但我不明白如何在这种情况下使用它。任何有帮助的将不胜感激。

【问题讨论】:

  • 您似乎正在尝试使用不同的界面复制自动完成功能。为什么不使用已经内置的 UI 功能?
  • 我猜自动完成是在用户输入时建议单词并附加到文本框内容的那个?不,这不是我的本意。我特别想在 listBox 中搜索在文本框中输入的单词。
  • 您应该在用户离开文本框或按enter后开始搜索。
  • @Fabio 这是个好主意。使用按钮并按 Enter 实际上确实让我想到了,但我真的很想使用 backgroundWorker 并在用户输入时进行搜索。因为我在很多应用程序中都看到过这种搜索方式。例如,音乐播放器“Winamp”有一个非常相似的搜索框,而且非常易于使用。当我在框中输入时,结果会被过滤得越来越多,直到我看到我想要的内容并停止输入。我想创造类似的东西......

标签: c# winforms search listbox backgroundworker


【解决方案1】:

使用 BackgroundWorker 类...

声明...

    BackgroundWorker listSearch = new BackgroundWorker();

初始化...

        listSearch.DoWork += ListSearch_DoWork;
        listSearch.RunWorkerCompleted += ListSearch_RunWorkerCompleted;

事件处理程序实现...

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        listSearch.RunWorkerAsync(textBox1.Text);
    }

    private void ListSearch_DoWork(object sender, DoWorkEventArgs e)
    {
        string text = e.Argument as string;
        List<string> items = new List<string>();
        foreach (string item in tempList)
        {
            if (item.ToLower().Contains(text.ToLower()))
            {
                items.Add(item);
            }
        }
        e.Result = items.ToArray();
    }

   private void ListSearch_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        string[] items = e.Result as string[];
        Invoke((Action)(() =>
        {
            listBox1.Items.Clear();
            foreach(string item in items)
            {
                listBox1.Items.Add(item);
            }
        }));
    }

【讨论】:

  • 太棒了!这和我想要的完全一样。感激不尽。
  • 注意:run worker 完成处理程序中的调用是多余的。我只是做了一个快速检查,完成的运行工作人员总是在创建后台工作人员的同一线程上运行。所以你可以简化一点。
【解决方案2】:

Task 类的使用比BackgroundWorker 容易得多。

试试这个简单的解决方案:

private async void TextBox_TextChanged(object sender, EventArgs e)
{
    listBox.DataSource = null;

    var task = Task.Run(() =>
        {
            var resultList = new List<string>();

            foreach (string item in tempList)
                if (item.ToLower().Contains(textBox.Text.ToLower()))
                    resultList.Add(item);

            return resultList;
        });

    listBox.DataSource = await task;
}

使用数据绑定来简化代码。在程序加载时,设置

listBox.DataSource = tempList;

【讨论】:

    猜你喜欢
    • 2011-08-03
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 2012-08-14
    • 1970-01-01
    相关资源
    最近更新 更多