Каков наилучший способ предотвратить потерю фокуса TextBox при ошибке проверки? - PullRequest
5 голосов
/ 29 января 2010

Я возился с PreviewLostKeyboardFocus, что почти привело вас туда. Я видел несколько реализаций, использующих LostFocus, но это просто заставляет фокусироваться обратно на TextBox после его потери фокуса, и вы можете легко увидеть это смещение на экране. По сути, я просто ищу то же поведение, которое вы можете получить, используя OnValidating в WinForms.

Ответы [ 3 ]

5 голосов
/ 31 января 2010

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

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

  1. Перехватывать Preview версию событий клавиатуры и мыши на уровне вашего окна или в любой области видимости, в которой вы хотите предотвратить изменение фокуса (например, возможно, не в строке меню).

  2. Если в текстовом поле обнаружена вкладка KeyDown или Return KeyDown или если MouseDown обнаружен за пределами текстового поля, когда оно имеет фокус, вызовите UpdateSource () для выражения привязки, а затем, если проверка имеет не удалось установить Handled = true, чтобы предотвратить дальнейшую обработку события KeyDown или MouseDown.

  3. Также продолжайте обработку PreviewLostKeyboardFocus, чтобы выявить любые причины изменения фокуса, не связанные с клавиатурой или мышью, или которые ваш другой код не распознал.

2 голосов
/ 26 июня 2011

Чтобы добавить ответ Рэя:

UpdateSource называется так:

BindingExpression be = userTextbox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();

Кроме того, в качестве альтернативы вы можете установить привязку текстового поля к:

UpdateSourceTrigger = "PropertyChanged";

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

1 голос
/ 17 декабря 2014

Если вы попытаетесь сфокусировать элемент внутри его собственного обработчика LostFocus, вы столкнетесь с StackOverflowException, я не уверен насчет основной причины (я подозреваю, что фокус фокусируется вокруг), но есть простой обходной путь: отправьте его.

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    var element = (sender as TextBox);
    if (!theTextBoxWasValidated())
    {
        // doing this would cause a StackOverflowException
        // element.Focus();
        var restoreFocus = (System.Threading.ThreadStart)delegate { element.Focus(); };
        Dispatcher.BeginInvoke(restoreFocus);
    }
}

Посредством Dispatcher.BeginInvoke вы гарантируете, что восстановление фокуса не мешает происходящей потере фокуса (и избегаете неприятного исключения, с которым вы столкнетесь в противном случае)

...