我有一个WinForm应用程序,在窗体上有几个输入控件。在验证事件处理程序(Validating
或Validated
)中,我需要根据验证的值确定接下来要激活的控件。
在Microsoft的Validating事件文档中,它声明:
注意
请勿尝试从Enter,GotFocus,Leave,LostFocus,Validating或Validated事件处理程序中设置焦点。这样做可能会导致您的应用程序或操作系统停止响应。有关详细信息,请参阅“键盘输入参考”部分中的WM_KILLFOCUS主题,以及MSDN库中的“关于消息和消息队列”主题的“消息死锁”部分,网址为:http:// msdn.microsoft.com/library
Form类有一个ActiveControl
属性,允许设置要变为活动的控件,并且没有提到任何限制。经过几个小时的网络搜索后,我还没有找到任何其他解决方案。
从我的Validated事件处理程序设置ActiveControl
属性(而不是Focus
)是一种安全的方式来积极激活我想要的控件吗?如果没有,有没有解决方案?
因为.NET Compact Framework没有ActiveControl
属性,所以有人可以提出解决方案吗?
答案 0 :(得分: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();
}
答案 1 :(得分:2)
您是否尝试将传递给Validating
事件处理程序的Cancel
property的CancelEventArgs
设置为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;
}
}
答案 2 :(得分:0)
Form.SelectNextControl或Control.SelectNextControl
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.selectnextcontrol.aspx
答案 3 :(得分:0)
这个帖子很老了,但我有几点想法:
每个控件都有一个Tag属性。如果给出你想要的控件,那么关注一个唯一的Tag值,然后创建一个迭代控件来找到该控件的方法?然后你可以设置焦点。
为什么不使用Leaving而不是使用Validating事件?似乎没有相同的怪癖。