Задержка действия KeyUp, если пользователь печатает (C #) - PullRequest
3 голосов
/ 01 июня 2010

У меня есть функция, которая вызывается, когда пользователь печатает в окне поиска. Я хочу подождать, пока пользователь закончит печатать, прежде чем я действительно выполню функцию. Я знаю, как легко сделать это в JavaScript с тайм-аутами, но как мне поступить так же в C #? Кроме того, как долго я должен ждать, прежде чем предположить, что пользователь закончил печатать? 100мс

Ответы [ 6 ]

5 голосов
/ 01 июня 2010

Вот мой рабочий код, основанный на вводе данных Лорен:

private void SearchTextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (SearchTextBoxTimer != null)
{
   Console.WriteLine("The user is currently typing.");
   if (SearchTextBoxTimer.Interval < 750)
   {
       SearchTextBoxTimer.Interval += 750;
       Console.WriteLine("Delaying...");
   }
}
else
{
    Console.WriteLine("The user just started typing.");
    SearchTextBoxTimer = new System.Windows.Forms.Timer();
    SearchTextBoxTimer.Tick += new EventHandler(SearchTextBoxTimer_Tick);
    SearchTextBoxTimer.Interval = 500;
    SearchTextBoxTimer.Start();
}
}

И обработчик событий:

private void SearchTextBoxTimer_Tick(object sender, EventArgs e)
{
    Console.WriteLine("The user finished typing.");
    if (SearchTextBox.Text == "")
    {
        ConsoleTextBox.Text = "Searching: All";
    }
    else
    {
        ConsoleTextBox.Text = "Searching: " + SearchTextBox.Text;
    }
    SearchTextBox_TextChanged();
    SearchTextBoxTimer.Stop();
    SearchTextBoxTimer.Dispose();
    SearchTextBoxTimer = null;
}

Если кто-то играет с этим кодом, дайте мне знать, если вы настроите времяинтервалы, которые я вставил. Я пока не думаю, что они оптимальны.

5 голосов
/ 01 июня 2010

Если вам удобно использовать инфраструктуру Reactive (Rx), то вы можете реализовать эту функцию, используя ее встроенное регулирование очень быстро.

Вот статья на эту тему: Rx может улучшить отзывчивость интерфейса

И некоторый код, украденный и измененный из статьи:

var textObserver = (from text in Observable.FromEvent<TextChangedEventArgs>(_app.myTextField, "TextChanged")
   select text).Throttle(TimeSpan.FromSeconds(.5));

_searchObserver = textObserver.Subscribe(textChangedEvent =>
   {
      var tb = (TextBox)textChangedEvent.Sender;
      DoMySearch(tb.Text);
   });

Как указано в статье (которую стоит прочитать полностью), она будет запускать код в лямбда-выражении всякий раз, когда проходит полсекунды, а пользователь ничего не печатает.

Я приведу пример в порядок завтра, когда буду перед своим ПК для разработки, но это должно дать вам отправную точку.

2 голосов
/ 01 июня 2010

Установите таймер на желаемый интервал задержки. Запустите таймер на событии Key Up. Если таймер срабатывает, вы останавливаете таймер и запускаете поиск.

100 мс - это НЕ хороший интервал, хотя !! Это примерно 100wpm, даже если печатание абсолютно ровное.

0 голосов
/ 15 августа 2018

Вот пример кода для решения этой проблемы

using System;
using System.Timers;
using System.Windows.Input;
using Timer = System.Timers.Timer;

namespace Example
{
    public partial class OnKeyUpInputExample
    {
        // Timer set to elapse after 750ms
        private Timer _timer = new Timer(750) { Enabled = false };

        // Constructor
        public OnKeyUpInputExample()
        {
            //What to do when _timer elapses
            _timer.Elapsed += TextInput_OnKeyUpDone;
        }

        // Event handler
        private void TextInput_OnKeyUp(object sender, KeyEventArgs e)
        {
            // You could also put the .Stop() in an OnKeyDown event handler if you need to account for keys being held down
            _timer.Stop();
            _timer.Start();
        }

        // Function to complement timer elapse
        private void TextInput_OnKeyUpDone(object sender, ElapsedEventArgs e)
        {
            // If we don't stop the timer, it will keep elapsing on repeat.
            _timer.Stop();

            this.Dispatcher.Invoke(() =>
            {
                //Replace with code you want to run.
                Console.WriteLine("KeyUp timer elapsed");
            });
        }
    }
}
0 голосов
/ 01 июня 2010

Одно из предложений - не удивлять пользователя. Как правило, это хороший принцип дизайна пользовательского интерфейса. Так что выполнять фактический поиск только тогда, когда текстовое поле теряет фокус. Одно дело показывать постепенно совпадающие строки поиска при вводе пользователем (например, Google), но другое - удивить пользователя незапрошенным поиском после некоторой задержки клавиатуры. Лично я нахожу это раздражающим, так как я часто задумываюсь о поисковой строке при ее вводе.

0 голосов
/ 01 июня 2010

Некоторые виды можно найти здесь: Задержанные вызовы функций

Запишите метку времени каждого события keyup и используйте класс Timer, чтобы отложить выполнение метода. Внутри этого метода вы можете определить, прекратил ли пользователь ввод текста, сравнивая текущее время с отметкой времени последнего события keyup. Вы можете поэкспериментировать с интервалом, обеспечив отзывчивость. Также разумно ограничивать количество попаданий и разрешать поиск не менее 3 символов.

Таймер: http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...