如何在.NET中验证后将焦点设置为控件

Sun*_*000 6 c# validation controls focus winforms

我有一个WinForm应用程序,在窗体上有几个输入控件.在验证事件处理程序(Validating或者Validated)中,我需要根据验证的值确定接下来要激活的控件.

在Microsoft的Validating事件文档中,它声明:

警告

不要尝试从Enter,GotFocus,Leave,LostFocus,Validating或Validated事件处理程序中设置焦点.这样做可能会导致您的应用程序或操作系统停止响应.有关详细信息,请参阅"键盘输入参考"部分中的WM_KILLFOCUS主题,以及MSDN库中的"关于消息和消息队列"主题的"消息死锁"部分,网址为:http:// msdn.microsoft.com/library .

ActiveControlForm类有一个属性,允许设置要变为活动的控件,并且不提及任何限制.经过几个小时的网络搜索后,我还没有找到任何其他解决方案.

从我的Validated事件处理程序设置ActiveControl属性(而不是Focus)一个安全的方式来积极激活我想要的控件?如果没有,有什么解决方案吗?

由于.NET Compact Framework没有该ActiveControl属性,任何人都可以提出解决方案吗?

Han*_*ant 10

是的,在验证事件期间更改焦点非常麻烦.事件在焦点变化的确切时间引发.就Windows而言,下一个控件已经获得了焦点,但逻辑形式状态仍然关注于正在验证的控件.将e.Cancel设置为true时,Winforms必须撤消Windows焦点状态.如果不这样做,它必须在事件发生后更新逻辑状态.当你自己改变焦点时,可能会出现各种各样的问题.

重要的是你要等到焦点被整理出来.最好的办法是延迟代码,直到所有内容都运行完毕并且表单再次处于空闲状态.您可以使用Control.BeginInvoke()方法干净地执行此操作.像这样的东西:

    private delegate void ChangeFocusDelegate(Control ctl);

    private void textBox1_Validating(object sender, CancelEventArgs e) {
        int value;
        if (!int.TryParse(textBox1.Text, out value)) e.Cancel = true;
        else {
            if (value == 1) this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox2);
            else this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox3);
        }
    }
    private void changeFocus(Control ctl) {
        ctl.Focus();
    }
Run Code Online (Sandbox Code Playgroud)