c# - 仅使用单个搜索BackgroundWorker的自动完成文本框 - 代码示例?

标签 c# wpf vb.net winforms autocomplete

这个问题之前已经被问过here ,但答案只是“使用BackgroundWorker”,我问是否有完整的代码示例可用。

我想创建一个与计时器一起使用的标准AutocompleteTextBox,这样只有一个BackgroundWorker在进行搜索 - 如果用户输入了更多的击键,但旧的搜索仍在运行 - 该搜索应该是优雅地取消(通过 CancelAsync),一旦取消,新的搜索就会开始。

实现起来并不是那么简单 - 有这方面的代码示例吗?

最佳答案

我怀疑您会找到一个代码示例来帮助您解决您在这里讨论的具体问题。我就是这样做的。这些代码都没有经过测试,所以要小心愚蠢的错误。

首先,子类 TextBoxBase 并添加两个基本方法来实现搜索逻辑,其签名如下:

private IEnumerable<string> PerformSearch(string text)
private DisplayResults(IEnumerable<string> results)

向该类添加一个名为 Worker 的私有(private) BackgroundWorker 字段,并将其 DoWorkRunWorkerCompleted 事件设置为 event名为 Worker_DoWorkWorker.RunWorkerCompleted 的处理程序。

覆盖OnTextChanged:

public override void OnTextChanged(TextChangedEventArgs e)
{
   base.OnTextChanged(e);
   // if we're already cancelling a search, there's nothing more to do until
   // the cancellation is complete.
   if (Worker.CancellationPending)
   {
      return;
   }
   // if there's a search in progress, cancel it.
   if (Worker.IsBusy)
   {
      Worker.CancelAsync();
      return;
   }
   // there's no search in progress, so begin one using the current value
   // of the Text property.
   Worker.RunWorkerAsync(Text);
}

Worker_DoWork 事件处理程序非常简单:

private void Worker_DoWork(object sender,
   RunWorkerCompletedEventArgs e)
{
   e.Result = PerformSearch((string) e.Argument);
}

Worker_RunWorkerCompleted 事件处理程序如下所示:

private void Worker_RunWorkerCompleted(object sender, 
   RunWorkerCompletedEventArgs e)
{
   // always check e.Error first, in case PerformSearch threw an exception.
   if (e.Error != null)
   {
      // in your version, you want to do real exception handling, not this.
      throw e.Error.InnerException;  
   }
   // if the worker was cancelled, it's because the user typed some more text, and
   // we want to launch a new search using what's currently in the Text property.
   if (e.Cancelled)
   {
      Worker.RunWorkerAsync(Text);
      return;
   }
   // if the worker wasn't cancelled, e.Result contains the results of the search.
   DisplayResults((IEnumerable<string> e.Result);
}

请注意,DisplayResults 应测试它对文本框状态所做的任何假设。例如,当用户启动搜索时,文本框可能已经可见或启用,但现在不可见或启用。如果您在模式对话框中使用此文本框并且用户在搜索运行时取消该对话框,会发生什么情况?

另请注意,如果您的应用程序中有此控件的多个实例,则每个实例都将具有不同的 BackgroundWorker,因此 PerformSearch 方法必须是线程化的,这一点很重要安全的。如果不是,它将必须实现锁定,这样,如果您在一个文本框中启动搜索,它会阻止并等待另一个文本框当前正在使用共享资源。

关于c# - 仅使用单个搜索BackgroundWorker的自动完成文本框 - 代码示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4705808/

相关文章:

c# - WPF 流文档布局

vb.net - 分配二进制常量

c# - 使用 C# 以编程方式操作 PostBackUrl

c# - "aaaa".StartsWith( "aaa") 返回 false

wpf - 使用数据绑定(bind)获取 TabItem 的索引

c# - WPF ListView SelectedItems 数据绑定(bind) MVVM

javascript - ASP.Net webservices 中的 JSON 数组类型解析

c# - 这个用于连接和声明事件的 C# 代码的 VB.NET 等价物是什么?

c# - 捕捉到网格鼠标锁定

c# - 表达式树和调用委托(delegate)