Я сомневаюсь, что вы найдете пример кода, который поможет вам с конкретными проблемами, о которых вы говорите здесь. Вот как я это сделаю. Ни один из этого кода не проверен, так что остерегайтесь глупых ошибок.
Сначала создайте подкласс 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
был поточно-ориентированным. Если это не так, он должен будет реализовать блокировку, чтобы при запуске поиска в одном текстовом поле он блокировался и ждал, если другое текстовое поле в данный момент использует общий ресурс.