.NET: событие TextChanged для TextBox не всегда срабатывает, хотя KeyUp и KeyDown запускаются - PullRequest
4 голосов
/ 06 января 2010

У меня очень странная проблема. Я заметил, что иногда при вводе текста в мой TextBox я теряю некоторые нажатия клавиш. Я добавил несколько операторов трассировки в события, перехваченные этим TextBox, и обнаружил, что когда я терял нажатия клавиш, все события KeyUp, KeyDown и KeyPress срабатывали правильно, но событие TextChanged никогда не срабатывало.

Кто-нибудь знает, почему это произойдет? Я мог бы списать это как «ошибку .NET», но я бы предпочел выяснить, есть ли здесь решение.

В случае, если есть предложение использовать события KeyUp / KeyDown, чтобы определить, изменился ли текст, там также есть проблема. KeyUp / KeyDown вызываются несколько раз при каждом нажатии клавиши, поэтому было бы очень трудно определить, печатал ли кто-то одну и ту же букву несколько раз.

Ответы [ 3 ]

3 голосов
/ 07 января 2010

Хммм ....

Это будет выстрел, но вы уже говорили, что у вас есть обработчики событий KeyUp, KeyDown и KeyPress, верно? Вы установили флаг e.Handled в true в обработчиках событий, посмотрите здесь:

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }

Посмотрите здесь в MSDN об этом свойстве Handled. (Если у вас установлен MSDN 2008 SP 1 локально, ссылка будет ms-help://MS.MSDNQTR.v90.en/fxref_system.windows.forms/html/dfc80b44-1d79-6315-cbea-1388a048c018.htm)

Цитировать:

Handled is implemented differently by different controls within Windows Forms. 
For controls like TextBox which subclass native Win32 controls, it is 
interpreted to mean that the key message should not be passed to the underlying 
native control. 

If you set Handled to true on a TextBox, that control will not pass the key 
press events to the underlying Win32 text box control, but it will still 
display the characters that the user typed. 

Может быть, он не установлен, т.е. e.Handled = false;, что препятствует запуску события TextChanged?

Можете ли вы проверить и подтвердить это?

Редактировать: После ответа dreadprivateryan я могу заподозрить (из-за отсутствия отправленного кода), основываясь на его ответе, e.Handled для true, когда нажата клавиша Enter, и false для всех остальных мой разум думает, что это причина, по которой в результате этого не принимаются никакие дальнейшие нажатия клавиш.

  • Пытаетесь ли вы установить фокус на другой элемент управления при нажатии клавиши Enter? Возможно, что и KeyUp, и KeyDown конфликтуют ...
  • Снимите клавиатуру и отключите ее ...
  • Мое предложение состоит в том, чтобы полностью изменить код, как показано на рисунке, вынуть либо KeyDown, либо KeyUp Event Handler, поскольку они, проще говоря, одинаковы, хорошо, технически, он назначен соответственно для нажатия клавиши вниз, а также, когда ключ отпущен. Посмотрите эту ссылку здесь . Похожий вопрос был размещен здесь на SO.

В приведенном ниже примере я использовал обработчик события keyUp для переключения фокуса на следующий доступный элемент управления при нажатии клавиши ввода. В обработчике событий KeyPress это просто фильтрует ввод и допускает только цифры 0-9 соответственно, все остальное отбрасывается. В этот обработчик событий включена возможность возврата клавиши Backspace для редактирования.

        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter) SendKeys.Send("{TAB}");
        }
        private const string VALID_KEYS = "0123456789";
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e) 
        {                  
            if (VALID_KEYS.IndexOf(char.ToUpper(e.KeyChar)) != -1 || e.KeyChar == (char)8) 
                 e.Handled = false;                                                               
            else                                                                                 
                 e.Handled = true;                                                                
}                                                                                        

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

1 голос
/ 06 января 2010

На самом деле я не знаю, но у меня есть случайное предположение: вы работаете на виртуальной машине?

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

0 голосов
/ 06 января 2010

Вы имеете в виду, что нажатие клавиши фактически потеряно и никогда не появляется в коробке?Или вы имеете в виду, что вы не получаете событие TextChanged для каждого нажатия клавиши?

Я полагаю, что событие TextChanged вызвано уведомлением EN_CHANGE операционной системы, которое отправляется через сообщение WM_COMMAND.Я знаю, что определенные виды сообщений в Windows «объединяются», чтобы избежать избыточных уведомлений.Например, это может происходить с сообщениями WM_MOUSEMOVE, и именно поэтому вы не получаете событие перемещения мыши для каждого пикселя, который мышь перемещает по экрану.

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

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