2010-06-24 6 views
8

Ho un TextBox con un evento TextChanged cablato. Alla fine sta facendo una query a un database SQL, quindi voglio limitare il numero di query.Come gestire l'evento TextChanged solo quando l'utente smette di digitare?

Voglio solo effettuare la query se l'utente non ha premuto un tasto in dire .. 300 millisecondi o così. Se per qualche motivo la query precedente è ancora in esecuzione, avrei bisogno di cancellarla e quindi di inviare una nuova query.

risposta

8

Creare un System.Windows.Forms.Timer e reimpostarlo (ad esempio, arrestarlo e avviarlo) dopo ogni pressione di un tasto. Se viene attivato l'evento del timer, disabilitare il timer.

+0

Questo è il metodo che ho usato e ha funzionato perfettamente. Sorprendentemente non ricevo eccezioni sull'aggiornamento dell'interfaccia utente da parte di un altro thread? – esac

+0

Vedere http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S1. La risposta breve è che l'evento viene eseguito nel thread dell'interfaccia utente. Il che ha senso, considerando che è nello spazio dei nomi 'System.Windows.Forms'. – Brian

+0

Si noti che il collegamento della rivista MSDN sopra non è più un collegamento diretto. Puoi ancora accedervi con [archive.org] (https://web.archive.org/web/20130219050936/http://msdn.microsoft.com/en-us/magazine/cc164015.aspx). Oppure, basta scaricare la rivista del febbraio 2004 da quella pagina. Se non hai un lettore CHM, puoi accedere all'articolo estraendo il file CHM usando 7zip e aprendo '/ MSDNMagazineFebruary2004en-us/TimersinNET/chm.htm' – Brian

0

Aggiungere un secondo actionlistener che viene chiamato ogni volta che l'utente preme un tasto qualsiasi e quando viene chiamato salva l'ora corrente su una variabile globale. Quindi, ogni volta che viene chiamato l'evento TextChanged, controlla per vedere la differenza di orario tra la variabile globale e l'ora corrente.

Se la differenza è inferiore a 300 millisecondi, avviare un timer per eseguire la query dopo 300 millisecondi. Quindi, se l'utente preme un altro tasto, ripristina prima il timer.

+0

Ciò richiede all'utente di attendere 300 ms e quindi digitare un altro carattere se si desidera inviare i risultati. – Brian

1

Utilizzare Reactive Framework per eseguire il trigger su una sequenza di eventi. Non sono sicuro che sia esattamente come funzionerebbe, ma puoi leggerlo qui (Reactive Extensions for .NET) e vedere se soddisferà le tue esigenze. Ci sono un sacco di esempi anche qui: Examples. L'esempio "Throttling" potrebbe essere quello che stai cercando.

0

1) Creare un timer.

2) Creare un gestore per l'evento Tick del timer. Su ogni spunta, verificare se è trascorso un tempo di inattività sufficiente e, in caso affermativo, arrestare il timer ed eseguire la query.

3) Ogni volta che si preme un tasto su quella casella di testo, RIAVVIARE il timer.

1

Grazie all'idea di @ Brian e this answer, ho trovato la mia versione di utilizzare un timer per gestire questo problema. Questo ha funzionato bene per me. Spero che aiuti anche gli altri:

private Timer _tmrDelaySearch; 
private const int DelayedTextChangedTimeout = 500; 
private void txtSearch_TextChanged(object sender, EventArgs e) 
{ 
    if (_tmrDelaySearch != null) 
    _tmrDelaySearch.Stop(); 

    if (_tmrDelaySearch == null) 
    { 
     _tmrDelaySearch = new Timer(); 
     _tmrDelaySearch.Tick += _tmrDelaySearch_Tick; 
     _tmrDelaySearch.Interval = DelayedTextChangedTimeout; 
    } 

    _tmrDelaySearch.Start(); 
} 

void _tmrDelaySearch_Tick(object sender, EventArgs e) 
{ 
    if (stcList.SelectedTab == stiTabSearch) return; 
    string word = string.IsNullOrEmpty(txtSearch.Text.Trim()) ? null : txtSearch.Text.Trim(); 

    if (stcList.SelectedTab == stiTabNote) 
    FillDataGridNote(word); 
    else 
    { 
     DataGridView dgvGridView = stcList.SelectedTab == stiTabWord ? dgvWord : dgvEvent; 
     int idType = stcList.SelectedTab == stiTabWord ? 1 : 2; 
     FillDataGrid(idType, word, dgvGridView); 
    } 

    if (_tmrDelaySearch != null) 
    _tmrDelaySearch.Stop(); 
} 
Problemi correlati