Автозаполнение TextBox только с одним поиском BackgroundWorker - пример кода? - PullRequest
2 голосов
/ 16 января 2011

Это спрашивалось раньше здесь , но ответом было просто «использовать BackgroundWorker», и я спрашиваю, есть ли в наличии полный пример кода.

Я хотел бы создать стандартный AutocompleteTextBox, который работает с таймером, так что только один BackgroundWorker работает над поиском - если пользователь нажал еще несколько нажатий клавиш, но старый поиск все еще выполняется - этот поиск должен отменен грациозно (через CancelAsync), и как только он будет отменен, начнется новый поиск.

Это не так тривиально реализовать - есть ли примеры этого кода?

Ответы [ 2 ]

3 голосов
/ 16 января 2011

Я сомневаюсь, что вы найдете пример кода, который поможет вам с конкретными проблемами, о которых вы говорите здесь. Вот как я это сделаю. Ни один из этого кода не проверен, так что остерегайтесь глупых ошибок.

Сначала создайте подкласс TextBoxBase и добавьте два основных метода для реализации логики поиска со следующими сигнатурами:

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

Добавить личное BackgroundWorker поле с именем Worker к классу и установить его DoWork и RunWorkerCompleted события для обработчиков событий с именами Worker_DoWork и Worker.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 был поточно-ориентированным. Если это не так, он должен будет реализовать блокировку, чтобы при запуске поиска в одном текстовом поле он блокировался и ждал, если другое текстовое поле в данный момент использует общий ресурс.

0 голосов
/ 16 января 2011

Я предлагаю использовать функцию Автозаполнение в System.Windows.Forms.TextBox. Вы можете настроить его и построить материал для завершения вокруг этого.

ПРИМЕЧАНИЕ. Функция автозаполнения доступна только в .NET 2.0

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...