Ich bezweifle, werden Sie ein Codebeispiel, die Sie mit den spezifischen Problemen hilft Sie hier besprochen. Hier ist, wie ich das machen würde. Nichts von diesem Code wird getestet, also hüte dich vor dummen Fehlern.
Zuerst Unterklasse TextBoxBase
und zwei grundlegende Methoden fügen Sie die Suchlogik zu implementieren, mit den folgenden Signaturen:
private IEnumerable<string> PerformSearch(string text)
private DisplayResults(IEnumerable<string> results)
hinzufügen ein privates BackgroundWorker
Feld Worker
auf die Klasse mit dem Namen und legen Sie seine DoWork
und RunWorkerCompleted
Ereignisse Ereignis Handler mit den Namen Worker_DoWork
und Worker.RunWorkerCompleted
.
Aufschalten 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);
}
Die Worker_DoWork
Event-Handler ist ziemlich einfach:
private void Worker_DoWork(object sender,
RunWorkerCompletedEventArgs e)
{
e.Result = PerformSearch((string) e.Argument);
}
Die Worker_RunWorkerCompleted
Event-Handler sieht ungefähr wie folgt aus:
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);
}
Beachten Sie, dass DisplayResults
sollte testen ein y Annahme es macht über den Zustand des Textfelds. Das Textfeld wurde möglicherweise angezeigt oder aktiviert, als der Benutzer die Suche startete und zum Beispiel jetzt nicht sichtbar oder aktiviert war. Was passiert, wenn Sie dieses Textfeld in einem modalen Dialog verwenden und der Benutzer den Dialog während der Suche abbricht?
Beachten Sie auch, dass, wenn Sie mehrere Instanzen dieses Steuerelements in Ihrer Anwendung haben, jeder eine andere BackgroundWorker
hat, so dass es wichtig ist, dass die PerformSearch
Methode threadsicher ist. Wenn dies nicht der Fall ist, muss die Sperre aktiviert werden. Wenn Sie eine Suche in einem Textfeld starten, wird sie blockiert und es wird abgewartet, ob ein anderes Textfeld die freigegebene Ressource verwendet.
Wo bekommen Sie die Liste der Vorschläge? Wenn Sie es von einer DB-Datei erhalten, wird CancelAsync Ihnen nicht helfen. –
Die Liste der Vorschläge zu erhalten ist eine relativ langwierige Operation des Iterierens durch eine speicherinterne Struktur und kann in der Mitte abgebrochen werden (obwohl es bis zu einer halben Sekunde dauern kann, bis der Abbruch stattfindet; ich will nicht Der UI-Thread wird während dieser Zeit angehalten.) –
Möchten Sie eine neue "AutoCompleteBox" erstellen, die auf diese Weise funktioniert, oder möchten Sie diese Funktion in der vorhandenen "AutoCompleteBox" im Toolkit verwenden? –