2010-01-29 8 views
5

He tenido problemas con PreviewLostKeyboardFocus que casi te lleva hasta allí. He visto un par de implementaciones usando LostFocus, pero eso solo fuerza el enfoque en el TextBox después de perder el foco y puede ver fácilmente este cambio en la pantalla. Básicamente, estoy buscando el mismo tipo de comportamiento que podría obtener usando OnValidating en WinForms.¿Cuál es la mejor manera de evitar perder el foco de TextBox cuando hay un error de validación?

+1

La captura de enfoque en un control puede conducir a una experiencia de usuario deficiente ... Solo asegúrese de dejar que los usuarios salgan de ese cuadro de diálogo/ventana fácilmente ... –

Respuesta

5

En mi opinión, la mejor manera es generalmente no hacerlo. Casi siempre es mejor desactivar los otros controles o evitar guardar hasta que el valor sea válido.

Pero si su diseño realmente necesita esta capacidad, esto es lo que debe hacer:

  1. Intercepción la versión Preview de eventos de teclado y ratón a su nivel de la ventana, o cualquier ámbito que desee evitar los cambios de enfoque dentro (por ejemplo, tal vez no su barra de menú).

  2. cuando se detecta el KeyDown Tab o Retorno KeyDown del cuadro de texto, o cuando se detecta un MouseDown fuera del cuadro de texto, mientras que tiene el foco, llame UpdateSource() en la expresión de enlace, a continuación, si la validación ha fallado set Handled = true para evitar que el evento KeyDown o MouseDown se procese aún más.

  3. También continúe manipulando PreviewLostKeyboardFocus para detectar cualquier causa de cambio de foco que no sea del teclado o del mouse, o que su otro código no reconoció.

+0

cómo atrapar eventos de mouse globales (nivel de ventana)? Si tenemos un control de contenedor y enfoque, debe permanecer dentro del editor hasta que se pasen los datos válidos. –

2

Para añadir a la respuesta de Ray:

UpdateSource se llama así:

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

También, como alternativa, se puede establecer la unión a la caja de texto:

UpdateSourceTrigger = "PropertyChanged"; 

Esto último causará una verificación continua, mientras que el primero comprobará cuando sea necesario (rendimiento).

1

Si intenta enfocar un elemento dentro de su propio manejador LostFocus se encontrará con una StackOverflowException, no estoy seguro sobre la causa raíz (sospecho que el tipo de foco rebota) pero hay una solución fácil: despacharla .

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); 
    } 
} 

A través Dispatcher.BeginInvoke a asegurarse de que la restauración del foco no se interpone en el camino de la pérdida en curso de enfoque (y evitar la excepción desagradable que le hace frente de otra manera)

Cuestiones relacionadas