2010-06-24 31 views
8

Tengo un TextBox con un evento TextChanged conectado. Al final, está haciendo una consulta a una base de datos SQL, por lo que quiero limitar el número de consultas.¿Cómo manejar el evento TextChanged solo cuando el usuario deja de escribir?

Solo quiero hacer la consulta si el usuario no ha presionado una tecla en, por ejemplo, 300 milisegundos o menos. Si por alguna razón la consulta anterior aún se está ejecutando, necesitaría cancelarla y luego emitir una nueva consulta.

Respuesta

8

Cree un System.Windows.Forms.Timer y reinícielo (por ejemplo, deténgalo y ejecútelo) después de cada pulsación de tecla. Si el evento del temporizador se activa, desactive el temporizador.

+0

Este es el método que utilicé y funcionó perfectamente. Sorprendentemente, no recibo ninguna excepción sobre la actualización de la interfaz de usuario por otro hilo. – esac

+0

Consulte http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S1. La respuesta corta es que el evento se ejecuta en el hilo de UI. Lo cual tiene sentido, considerando que está en el espacio de nombres 'System.Windows.Forms'. – Brian

+0

Tenga en cuenta que el enlace de la revista MSDN anterior ya no es un enlace directo. Aún puede acceder a él con [archive.org] (https://web.archive.org/web/20130219050936/http://msdn.microsoft.com/en-us/magazine/cc164015.aspx). O simplemente descargue la revista de febrero de 2004 de esa página. Si no tiene un lector de CHM, puede acceder al artículo extrayendo el archivo CHM usando 7zip y abriendo '/ MSDNMagazineFebruary2004en-us/TimersinNET/chm.htm' – Brian

0

Agregue un segundo actionlistener al que se llama cada vez que el usuario presiona una tecla y cuando se llama guarde la hora actual en una variable global. Luego, cuando se llame a su evento TextChanged, verifica la diferencia de tiempo entre la variable global y la hora actual.

Si la diferencia es inferior a 300 milisegundos, inicie un temporizador para ejecutar la consulta después de 300 milisegundos. Luego, si el usuario presiona otra tecla, restablece el temporizador primero.

+0

Esto requiere que el usuario espere 300ms y escriba otro carácter si desea enviar los resultados. – Brian

1

Utilice el marco reactivo para activar una secuencia de eventos. No estoy seguro de exactamente cómo funcionaría esto, pero puede leerlo aquí (Reactive Extensions for .NET) y ver si satisfará sus necesidades. También hay muchos ejemplos aquí: Examples. El ejemplo de "Estrangulamiento" puede ser lo que estás buscando.

0

1) Crear un temporizador.

2) Cree un controlador para el evento Tick de su temporizador. En cada tilde, verifique si ha transcurrido suficiente tiempo de inactividad, y si lo ha hecho, DETÉNGASE y ejecute la consulta.

3) Cada vez que se produce una pulsación de tecla en ese cuadro de texto, reinicie el temporizador.

1

Gracias a la idea de @ Brian y al this answer, se me ocurrió mi propia versión del uso de un temporizador para manejar este problema. Esto funcionó bien para mi. Espero que también ayude a los demás:

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(); 
} 
Cuestiones relacionadas