2010-01-29 1 views
5

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

+1

Ловля фокус в управлении может привести к плохому пользовательскому опыту ... Просто не забудьте позволить пользователям быстро выйти из этого диалогового окна/окна ... –

ответ

5

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

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

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

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

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

+0

Как поймать глобальные (оконные уровни) события мыши? Если у нас есть контроль контейнера, и фокус должен оставаться внутри редактора, пока не будут приняты действительные данные. –

2

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

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

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

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

UpdateSourceTrigger = "PropertyChanged"; 

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

1

Если вы попытаетесь сфокусировать элемент внутри своего собственного обработчика 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 вы убедитесь, что восстановление фокуса не становится на пути потери незавершенного фокуса (и избежать противный исключение вы столкнуться в противном случае)