2009-07-31 3 views
7

Soy muy nuevo en .Net y WPF y tengo un problema. El código es un fragmento. Tengo TextBox es para ingresar las fechas. Verifico la entrada correcta usando los eventos GotFocus y LostFocus.WPF TextBox.Focus() fastidio

<TextBox Name="sdDay" Width="40" Text="Day" GotFocus="DateDay_GotFocus" LostFocus="DateDay_LostFocus" Padding="5,5,5,5" HorizontalContentAlignment="Center" Focusable="True"/> 
<TextBox Name="sdMonth" Width="50" Text="Month" GotFocus="DateMonth_GotFocus" LostFocus="DateMonth_LostFocus" Padding="5,5,5,5" Margin="5,0,0,0" HorizontalContentAlignment="Center" Focusable="True"/> 
<TextBox Name="sdYear" Width="50" Text="Year" GotFocus="DateYear_GotFocus" LostFocus="DateYear_LostFocus" Padding="5,5,5,5" Margin="5,0,0,0" HorizontalContentAlignment="Center" Focusable="True"/> 

Y el código:

private void DateDay_GotFocus(object sender, RoutedEventArgs e) 
    { 
     if (((TextBox)sender).Text == "Day") 
      ((TextBox)sender).Text = string.Empty; 
    } 

private void DateDay_LostFocus(object sender, RoutedEventArgs e) 
    { 
     if (((TextBox)sender).Text == string.Empty) 
      ((TextBox)sender).Text = "Day"; 
     else 
      CheckForCorrectDateDay((TextBox)sender); 
    } 

private void CheckForCorrectDateDay(TextBox b) 
    { 
     int day = 0; 

     try 
     { 
      day = int.Parse(b.Text); 

      if (day < 0 || day > 31) 
      { 
       MessageBox.Show("Please enter a correct day."); 
       b.Text = string.Empty; 
       b.Focus(); 
      } 
     } 
     catch (FormatException) 
     { 
      MessageBox.Show("Please enter a number.", "Incorrect Input", MessageBoxButton.OK, MessageBoxImage.Warning); 
      b.Text = string.Empty; 
      b.Focus(); 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
    } 

Ahora lo que quiero que haga es cheque de entrada correcta, y si eso no funciona, establecer el foco a lo TextBox tenía una entrada incorrecta.

Aunque no funciona. Después de ingresar un número fuera del rango (o letra), se mostrará MessageBox, pero el foco cambia al siguiente TextBox que es para ingresar el mes.

¿Qué estoy haciendo mal?

Respuesta

14

Su técnica para la validación aquí es, para ser franco, muy pobre. Dicho esto, creo que el problema es que WPF está manejando la pestaña después de establecer el foco, por lo que vuelve a centrar el foco en el siguiente elemento de la orden de enfoque.

Una solución sencilla sería la de enviar un mensaje separado que se procesa después del mensaje actual:

if (day < 0 || day > 31) 
{ 
    MessageBox.Show("Please enter a correct day."); 
    b.Text = string.Empty; 

    Dispatcher.BeginInvoke((ThreadStart)delegate 
    { 
     b.Focus(); 
    }); 
} 

Esto garantiza que WPF procesa por completo el controlador de LostFocus evento antes de que procesa el mensaje separado para establecer el foco en el control erróneo.

En términos de cómo se puede hacer frente a este problema de una manera mucho más agradable, usted podría:

  1. Definir un modelo de vista con propiedades para el día, mes y año (requisito previo: leer sobre el patrón MVVM)
  2. Implementar IDataErrorInfo en el modelo de vista
  3. Enlazar los TextBox ES en la interfaz de usuario a las propiedades correspondientes en el modelo de vista (requisito: leer sobre el enlace de datos WPF)
+0

Gracias por la respuesta. Entiendo tu explicación del problema, pero no es exactamente lo que hace la solución. Como dije, soy muy nuevo en .Net. Y no me importaría algunos consejos sobre mejores técnicas de validación. – Moss

+0

Claro. Se agregó más detalles a mi publicación. –

+0

Me gustaría hacerme eco del comentario de Kent: forzar la atención hacia atrás es una forma segura de enojar a los usuarios. –