Title: Expand a ComboBox when the user presses Enter in C#
A ComboBox control's DropDownStyle property determines how it lets the user select values. The three possible DropDownStyle values are:
- Simple - The ComboBox displays a text box (where the user can type a value) and a list (where the user can select a value)
- DropDown - The ComboBox displays a text and a list that the user can expand by clicking on the control's dropdown arrow
- DropDownList - The ComboBox displays a list that the user can expand by clicking on the control's dropdown arrow
Because the third option, DropDownList, only lets the user select from the list, that setting is particularly useful for preventing the usrer from entering gibberish.
One drawback to the DropDown and DropDownList styles is that the user cannot see the items in the list without using the mouse to make it drop down. That means users must take their hands off of the keyboard to position and click the mouse, and that makes the users slower.
This example shows one way you can change that.
Enter the Enter Key
This example lets you press Enter to expand a ComboBox control's list. You can then use the arrow keys to move up and down through the list. If you press Enter again, the list closes. (You can also close the list by pressing Escape.)
The obvious thing to do is to catch the control's KeyPress event and expand the list when you see the Enter key. That almost works.
The KeyPress event handler can detect the Enter key and open the control's drop down list. Unfortunately when you press Enter again, the list closes and then immediately reopens. The problem is that the control normally closes the list when it sees the Enter key. When you press Enter the second time, the control closes its list and then the KeyPres event handler reopens it.
You can make the event handler check the control's DroppedDown property to see if the list is currently dropped down and then do nothing if the list is visible. Unfortunately the control closes the list before the KeyPress event handler executes, so the event handler always sees the list as hidden so it always reopens it.
To make matters stranger, the control behaves slightly differently when using the DropDown and DropDownList styles. Checking the DroppedDown property works for the DropDown style but not for the DropDownList style.
The workaround I found is to keep track of the time when a ComboBox list was last closed. If less than 0.1 seconds have passed since the list was last closed, then the KeyPress event handler should not reopen it.
Here's the code that tracks when a ComboBox list was closed.
private DateTime LastCloseTime = DateTime.Now;
// Record the time when we closed a ComboBox.
private void cbo_DropDownClosed(object sender, EventArgs e)
{
LastCloseTime = DateTime.Now;
}
The variable LastCloseTime stores the last time that a ComboBox list was closed.
The cbo_DropDownClosed event handler simply records the current time.
The following code shows the KeyPress event handler that opens ComboBox lists.
private void cbo_KeyPress(object sender, KeyPressEventArgs e)
{
// See if the user pressed Enter.
if (e.KeyChar == (char)Keys.Enter)
{
// See if the list is already dropped.
ComboBox cbo = sender as ComboBox;
if (cbo.DroppedDown) return;
// See if it has been at least 0.1 seconds since
// the last time we closed a ComboBox.
TimeSpan time_since_close = DateTime.Now - LastCloseTime;
if (time_since_close.TotalSeconds < 0.1) return;
// Drop the list.
cbo.DroppedDown = true;
e.Handled = true;
}
}
If the key that was pressed is Enter, then the code first checks whether the ComboBox list is open. If the list is open, then the event handler exits and lets the control's normal behavior collapse the list.
If the list is not already open, the code calculates the time that has elapsed since the last time that a ComboBox list was closed. If that time is less than 0.1 seconds, then the list has just closed so the program should not reopen it. In that case the event handler simply exits.
If more than 0.1 second has passed since a list was closed, the code sets the control's DroppedDown property to true to make the list drop down. The code finishes by setting e.Handled to true so the control does not try to process the key press further.
Strangely all of the pieces of the event handler seem to be necessary even though some seem redundant.
- If you comment out the if (cbo.DroppedDown) return statement, then a ComboBox using the DropDown style will not let you close the list by pressing Enter.
- If you comment out the if (time_since_close.TotalSeconds < 0.1) return; statement, then a ComboBox using the DropDownList style immediately reopens the list after you use Enter to close it.
- If you comment out the e.Handled = true statement, then a ComboBox using the DropDown style immediately closes its list after you use Enter to open it.
To allow the user to press Enter to open and close ComboBox lists, simply attach the cbo_DropDownClosed and cbo_KeyPress event handlers to any ComboBox controls that you want to have this behavior. Note that the event handlers have no effect if the ComboBox has the Simple style, so it doesn't hurt much to attach the event handlers to all ComboBox controls.
Conclusion
The event handlers shown here let the user quickly expand and collapse ComboBox lists by using only the keyboard. You can certainly do without this feature, but it can make data entry significantly faster if you need to fill in many ComboBox fields.
Download the example program to see additional details and to experiment with the program.
Download the example to experiment with it and to see additional details.
|