WPF TextBox.Focus()烦恼

Mos*_*oss 7 wpf textbox focus

我对.Net和WPF很新,但有问题.代码是一个片段.我TextBox要输入日期.我使用GotFocusLostFocus事件检查正确的输入.

<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"/>
Run Code Online (Sandbox Code Playgroud)

和代码:

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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在我想要它做的是检查输入是否正确,如果失败,将焦点设置回任何TextBox有错误输入的内容.

它不起作用.输入范围(或字母)之外的数字后,MessageBox将显示但焦点将转移到下一个用于输入月份的TextBox.

我究竟做错了什么?

Ken*_*art 14

坦率地说,你的验证技术非常差.也就是说,我认为问题只是WPF在您设置焦点后处理选项卡,因此它将焦点设置回焦点顺序中的下一个项目.

一个简单的解决方法是分派在当前消息之后处理的单独消息:

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

    Dispatcher.BeginInvoke((ThreadStart)delegate
    {
        b.Focus();
    });
}
Run Code Online (Sandbox Code Playgroud)

这样做可确保WPF LostFocus在处理单独的消息之前完全处理事件处理程序,以便将注意力集中在错误的控件上.

就如何以更好的方式解决这个问题而言,你可以:

  1. 使用日,月和年的属性定义视图模型(先决条件:在MVVM模式上阅读)
  2. 实现IDataErrorInfo对视图模型
  3. TextBox将UI中的es 绑定到视图模型上的相应属性(先决条件:阅读WPF数据绑定)