【问题标题】:How to set focus to a control after validation in .NET如何在 .NET 中验证后将焦点设置到控件
【发布时间】:2010-12-16 18:42:36
【问题描述】:

我有一个 WinForm 应用程序,一个表单上有多个输入控件。在验证事件处理程序(ValidatingValidated)中,我需要根据验证值确定接下来要激活的控件。

在 Microsoft 的 Validating 事件文档中,它指出:

注意

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

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

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

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

【问题讨论】:

    标签: c# winforms validation focus controls


    【解决方案1】:

    是的,在验证事件期间更改焦点非常麻烦。该事件在焦点更改的确切时间引发。就 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();
        }
    

    【讨论】:

    • 哇,聪明的回答!我认为委托方法必须调用 EndInvoke(),但那是在我知道 Delegate.BeginInvoke() 和 Control.BeginInvoke() 之间的区别之前。见[.net - Invoke() 和 BeginInvoke 有什么区别][1] [1]stackoverflow.com/questions/229554/…
    【解决方案2】:

    您是否尝试将传递给Validating 事件处理程序的CancelEventArgsCancel property 设置为False?

    这是将焦点保持在当前控件上并防止下一个控件在验证失败时获得焦点的预期方式。例如:

    private void TextBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
    {
        //Make sure that the textbox is not left blank
        if (string.IsNullOrEmpty(TextBox1.Text))
        {
            e.Cancel = true;
        }
    }
    

    【讨论】:

    • 谢谢。我知道这一点,但它只会让焦点保持不变。它不允许将焦点设置到特定控件。
    • @Suncat:是的,我无法从问题中看出您想将焦点设置为不同的控件。汉斯已经给你一个很好的答案,告诉你如何做到这一点。
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      这个帖子很旧,但我有几个想法:

      1. 每个控件都有一个 Tag 属性。给你想要的控件一个唯一的 Tag 值,然后创建一个方法来遍历控件以找到该控件怎么样?然后你可以设置焦点。

      2. 为什么不使用验证事件,而不是使用离开呢?似乎没有相同的怪癖。

      【讨论】:

        猜你喜欢
        • 2012-07-12
        • 1970-01-01
        • 2017-01-21
        • 2011-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多