I have a form with CancelButton and AcceptButton (named btnCancel and btnOK). And I have some ComboBoxes as input fields.
ComboBoxes prevent my AcceptButton and CancelButton to receive Escape and Enter keys, so I added this code to KeyDown event for all fields:
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();
}
}
This is the code in Clicked event of OK button:
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);
}
Everything is OK but when a ComboBox has Focus and I press Enter key on my keyboard, btnOK_Clicked calls Fields_KeyDown again only when it shows its MessageBox (on else part of if). Exactly right after MessageBox.Show(...) is being called, KeyDown event is being called for second time without any reason.
This is Call Stack for first call:
And this is for second:
Second call should not occur at all. In second Call Stack, first btnOK_Click (third line) again calls Fields_KeyDown (second line) from MessageBox.Show(...). How is this possible? I'm confused...
Call Stack for second call with External Code visible:
While I have no idea about the main reason behind this behavior.
But in this situation obviously
KeyDown
event triggers 2 times. (Set a breakpoint and you will see.)Since you need to handle it in code, You can try this to neglect one of Enter keys:
You cannot correctly process Escape and Enter key in KeyDown event because they are handled during the keyboard preprocessing phase - Control.IsInputKey and Control.ProcessDialogKey. Normally controls do that for you, but looks like there is a bug in
ComboBox
implementation whenDropDownStyle
isSimple
.To get the desired behavior, create and use your own
ComboBox
subclass like thisP.S. And of course don't forget to remove your KeyDown event handlers.