2011-01-16 11 views
2

Dies wurde vor here gefragt, aber die Antwort dort war einfach "verwenden BackgroundWorker", und ich frage, ob es eine vollständige Codebeispiel verfügbar ist.AutoComplete TextBox mit nur einer einzigen Suche BackgroundWorker - Codebeispiel?

Ich möchte eine Standard-AutocompleteTextBox erstellen, die mit einem Timer arbeitet, so dass nur ein BackgroundWorker an der Suche arbeitet - wenn der Benutzer noch ein paar Tastenanschläge eingibt, aber die alte Suche noch läuft - soll diese Suche erfolgen abgebrochen werden (via CancelAsync), und sobald es abgebrochen wird, beginnt die neue Suche.

Dies ist nicht so trivial zu implementieren - gibt es Code Beispiele davon?

+1

Wo bekommen Sie die Liste der Vorschläge? Wenn Sie es von einer DB-Datei erhalten, wird CancelAsync Ihnen nicht helfen. –

+0

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.) –

+0

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? –

Antwort

3

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.

+0

Danke für die vollständige Antwort. –

0

Ich empfehle die Verwendung der AutoComplete Funktion in System.Windows.Forms.TextBox. Sie können es anpassen und bauen Sie Ihre Abschlussarbeiten darum herum.

HINWEIS: Auto-Vervollständigen-Funktion ist nur von .NET 2.0

+0

Das hilft mir nicht, da dieses Feature eine StringCollection erwartet, die es durchsuchen kann, wobei es (ganz richtig) davon ausgeht, dass die Suche in einer StringCollection sofort erfolgt. In meinem Szenario ist die Suche länger und komplexer - und kann einige Sekunden dauern. –

Verwandte Themen