Как обрабатывать событие TextChanged только тогда, когда пользователь перестает печатать?

У меня есть TextBox с подключенным событием TextChanged. В конце концов, он делает запрос к базе данных SQL, поэтому я хочу ограничить количество запросов.

Я хочу сделать запрос только если пользователь не нажал клавишу, скажем, .. 300 миллисекунд или около того. Если по какой-то причине предыдущий запрос все еще выполняется, мне нужно будет отменить его, а затем выполнить новый запрос.


person esac    schedule 24.06.2010    source источник


Ответы (5)


Создайте System.Windows.Forms.Timer и сбросьте его (например, остановите, а затем запустите) после каждого нажатия клавиши. Если событие таймера срабатывает, отключите таймер.

person Brian    schedule 24.06.2010
comment
Это метод, который я использовал, и он работал отлично. Удивительно, но я не получаю никаких исключений об обновлении пользовательского интерфейса другим потоком? - person esac; 24.06.2010
comment
См. msdn.microsoft.com/en-us/magazine/cc164015.aspx. #S1 . Короткий ответ: событие выполняется в потоке пользовательского интерфейса. Что имеет смысл, учитывая, что он находится в пространстве имен System.Windows.Forms. - person Brian; 24.06.2010

Используйте Reactive Framework для запуска последовательности событий. Я не уверен, точно как это будет работать, но вы можете прочитать об этом здесь (Reactive Extensions for .NET) и посмотрите, удовлетворит ли он ваши потребности. Здесь также есть множество примеров: Примеры. Пример «Дросселирование» может быть тем, что вы ищете.

person Garo Yeriazarian    schedule 24.06.2010

1) Создайте таймер.

2) Создайте обработчик события Tick вашего таймера. На каждом тике проверяйте, истекло ли достаточно времени простоя, и если да, ОСТАНОВИТЕ таймер и выполните запрос.

3) Всякий раз, когда в этом текстовом поле происходит нажатие клавиши, ПЕРЕЗАПУСКАЙТЕ таймер.

person seraphym    schedule 24.06.2010

Добавьте второй прослушиватель действий, который вызывается всякий раз, когда пользователь нажимает любую клавишу, и когда он вызывается, сохраняет текущее время в глобальной переменной. Затем, когда вызывается ваше событие TextChanged, оно проверяет разницу во времени между глобальной переменной и текущим временем.

Если разница меньше 300 миллисекунд, запустите таймер для выполнения запроса через 300 миллисекунд. Затем, если пользователь нажимает другую клавишу, он сначала сбрасывает таймер.

person Kyra    schedule 24.06.2010
comment
Это требует от пользователя ожидания 300 мс, а затем ввода другого символа, если он хочет отправить результаты. - person Brian; 24.06.2010

Благодаря идее @Brian и этому ответу я придумал собственную версию использования таймера для решения этой проблемы. Это отлично сработало для меня. Я надеюсь, что это поможет и другим:

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();
}
person Alex Jolig    schedule 08.12.2015