我有一个带有CancelButton和AcceptButton的表单(名为btnCancel和btnOK)。我有一些ComboBoxes作为输入字段。
ComboBox会阻止我的AcceptButton和CancelButton接收Escape和Enter键,因此我将此代码添加到所有字段的KeyDown事件中:
if (e.KeyData == Keys.Escape)
{
ComboBox field = (ComboBox)sender;
if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
{
e.SuppressKeyPress = true;
btnCancel.PerformClick();
}
}
else if (e.KeyData == Keys.Enter)
{
ComboBox field = (ComboBox)sender;
if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
{
e.SuppressKeyPress = true;
btnOK.PerformClick();
}
}
这是OK按钮的Clicked事件中的代码:
if (!changesAreSaved)
{
SaveChangesToNode();
}
List<int> invalidIndices = ValidateAndRefineNodes(true);
if (invalidIndices.Count == 0)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show(this, "Enter correct values for all fields before you press OK.", "Cannot Save Information",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
一切正常但是当ComboBox有Focus并且我按下键盘上的Enter键时,btnOK_Clicked在显示其MessageBox(在if的其他部分)时再次调用Fields_KeyDown 。正好在调用MessageBox.Show(...)之后,第二次调用KeyDown事件而没有任何理由。
这是第一次通话的呼叫堆栈:
这是第二次:
根本不应该发生第二次通话。在第二个调用堆栈中,首先btnOK_Click(第三行)再次从MessageBox.Show(...)调用Fields_KeyDown(第二行)。这怎么可能?我很困惑......
呼叫堆栈以进行第二次呼叫,外部代码可见:
答案 0 :(得分:1)
虽然我不知道这种行为背后的主要原因。
但在这种情况下,显然KeyDown
事件会触发2次。 (设置一个断点,你会看到。)
由于您需要在代码中处理它,您可以尝试忽略 Enter 键之一:
bool handled = true;
private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
/*Prevent handling the Enter key twice*/
handled = !handled;
if(handled)
return;
//Rest of logic
//OkButton.PerformClick();
}
}
答案 1 :(得分:1)
您无法在KeyDown事件中正确处理Escape和Enter键,因为它们是在键盘预处理阶段处理的 - Control.IsInputKey和Control.ProcessDialogKey。通常控件会为您执行此操作,但在ComboBox
为DropDownStyle
时,Simple
实现中存在错误。
要获得所需的行为,请创建并使用您自己的ComboBox
子类,如下所示
public class MyComboBox : ComboBox
{
protected override bool IsInputKey(Keys keyData)
{
if (DropDownStyle == ComboBoxStyle.Simple)
{
switch (keyData & (Keys.KeyCode | Keys.Alt))
{
case Keys.Return:
case Keys.Escape:
return false;
}
}
return base.IsInputKey(keyData);
}
}
P.S。当然不要忘记删除KeyDown事件处理程序。