2009-07-31 5 views
7

Jestem bardzo nowy w .Net i WPF i mam problem. Kod jest fragmentem. Mam TextBox es wpisać daty. Sprawdzam poprawne dane wejściowe, używając zdarzeń GotFocus i LostFocus.WPF TextBox.Focus() irytacja

<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"/> 

I kod:

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

Teraz to, co chcę zrobić, to sprawdzić poprawność danych wejściowych, a jeśli to się nie powiedzie, ustawić ostrość z powrotem do tego, co TextBox miał błędny wpis.

To jednak nie działa. Po wprowadzeniu numeru spoza zakresu (lub litery) pojawi się MessageBox, ale fokus zostanie przeniesiony do następnego pola tekstowego, które służy do wprowadzania miesiąca.

Co robię źle?

Odpowiedz

14

Twoja technika walidacji jest tutaj, szczerze mówiąc, bardzo słaba. To powiedziawszy, uważam, że problem polega tylko na tym, że WPF obsługuje zakładkę po ustawieniu ostrości, więc ustawia fokus z powrotem do następnego elementu w kolejności ustawiania ostrości.

Prosty obejście byłoby wysyłką oddzielny komunikat, który jest przetwarzany po bieżącej wiadomości:

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

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

Rozwiązanie to gwarantuje, że WPF całkowicie przetwarza obsługi LostFocus zdarzeń przed przetwarza oddzielny komunikat, aby ustawić skupić się na błędna kontrola.

W kategoriach jak można rozwiązać ten problem w znacznie przyjemniejszy sposób, można:

  1. zdefiniowanie modelu widok z mieszkań na dzień, miesiąc i rok (warunek: przeczytać na wzór MVVM)
  2. Wdrożenie IDataErrorInfo modelu widok
  3. oprawę z TextBox ES w interfejsie do odpowiednich właściwości w modelu widzenia (warunek: przeczytać danych WPF wiążących)
+0

Dziękuję za odpowiedź. Rozumiem twoje wyjaśnienie problemu, ale nie dokładnie to, co robi to rozwiązanie. Tak jak powiedziałem, jestem bardzo nowy w .Net. I nie miałbym nic przeciwko niektórym wskazówkom na temat lepszych technik sprawdzania poprawności. – Moss

+0

Pewnie. Dodałem trochę więcej szczegółów do mojego posta. –

+0

Chciałbym powtórzyć komentarz Kenta - wymuszenie skupienia z powrotem jest pewnym sposobem na złość użytkowników. –