WPF TextBox.Focus () раздражение - PullRequest
7 голосов
/ 31 июля 2009

Я очень новичок в .Net и WPF и у меня проблема.Код является фрагментом.У меня есть TextBox es для ввода даты.Я проверяю правильность ввода, используя GotFocus и LostFocus события.

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

И код:

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

Теперь я хочу проверить правильность ввода,и если это не удается, установите фокус на то, что TextBox имеет неправильную запись.

Это не работает, хотя.После ввода числа вне диапазона (или буквы) будет отображаться MessageBox, но фокус смещается на следующий текстовый блок, предназначенный для ввода месяца.

Что я делаю неправильно?

1 Ответ

14 голосов
/ 31 июля 2009

Ваша техника проверки здесь, прямо скажем, очень плохая. Тем не менее, я считаю, что проблема в том, что WPF обрабатывает вкладку после того, как вы установили фокус, поэтому он возвращает фокус к следующему элементу в порядке фокусировки.

Простой обходной путь - отправить отдельное сообщение, которое обрабатывается после текущего сообщения:

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

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

Это гарантирует, что WPF полностью обработает обработчик события LostFocus, прежде чем обрабатывать отдельное сообщение, чтобы сфокусироваться на ошибочном элементе управления.

С точки зрения того, как вы можете решить эту проблему намного лучше, вы можете:

  1. Определение модели представления со свойствами для дня, месяца и года (предварительное условие: чтение по шаблону MVVM)
  2. Реализация IDataErrorInfo в представлении модели
  3. Привязать TextBox es в пользовательском интерфейсе к соответствующим свойствам в модели представления (предварительное условие: чтение привязки данных WPF)
...