2009-07-31 6 views
7

Sono molto nuovo per .Net e WPF e avere un problema. Il codice è uno snippet. Ho TextBox es per inserire le date. Controllo l'input corretto usando gli eventi GotFocus e 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"/> 

E il codice:

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

Ora quello che voglio fare è controllare per ingresso corretto, e se non funziona, impostare la messa a fuoco posteriore a qualunque TextBox avuto un inserimento errato.

Non funziona però. Dopo aver inserito un numero al di fuori dell'intervallo (o della lettera), verrà visualizzato il numero MessageBox, ma lo stato attivo passerà al successivo TextBox che consente di accedere al mese.

Cosa sto sbagliando?

risposta

14

tua tecnica per la convalida qui è, per dirla tutta, molto povera. Detto questo, credo che il problema sia solo il fatto che WPF sta gestendo la scheda dopo aver impostato lo stato attivo, quindi imposterà nuovamente l'elemento successivo nell'ordine di messa a fuoco.

Una soluzione semplice sarebbe quella di inviare un messaggio separato che viene elaborato dopo il messaggio corrente:

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

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

In questo modo si assicura che WPF elabora completamente il gestore LostFocus evento prima che elabora il messaggio separato per impostare concentrarsi su il controllo errato.

in termini di come si potrebbe affrontare questo problema in un modo molto più bello, si potrebbe:

  1. Definire un modello di vista con le proprietà per giorno, mese e anno (prerequisito: documentarsi sul modello MVVM)
  2. Implementare IDataErrorInfo sul modello vista
  3. Bind le TextBox es nell'interfaccia utente alle proprietà corrispondenti sul modello vista (prerequisito: leggere su dati WPF vincolanti)
+0

Grazie per la risposta. Capisco la tua spiegazione del problema ma non esattamente ciò che fa la soluzione. Come ho detto, sono molto nuovo a .Net. E non mi dispiacerebbe alcuni suggerimenti su tecniche di validazione migliori. – Moss

+0

Sicuro. Aggiunti altri dettagli al mio post. –

+0

Vorrei fare eco al commento di Kent: forzare l'attenzione è un modo sicuro per far arrabbiare i tuoi utenti. –