Click here to Skip to main content
13,450,958 members (56,185 online)
Click here to Skip to main content
Add your own
alternative version


98 bookmarked
Posted 20 Nov 2008

A ComboBox with a CheckedListBox as a Dropdown

, 22 Nov 2008
Rate this:
Please Sign up or sign in to vote.
A ComboBox with a CheckedListBox as a dropdown


This control came out of my need to create a CheckedListBox control which does not occupy as much space on the form while the selected item(s) are visible. Although a few examples already exist using owner-drawn controls (i.e., drawing the ListBox portion of the ComboBox), I wasn't fully satisfied because of some shortcomings, hence I came up with a new version, the CheckedComboBox which has the following features:

  • Read-only text portion, displaying the checked item(s).
  • Each checked item appears in the text portion as a string, each string separated by a custom separator that I may define.
  • List portion stays open until the user finishes the selection.
  • Check/uncheck all items.
  • Display/hide the list portion via the keyboard.
  • Mimic as closely as possible the .NET ComboBox.
  • Use it from the Visual Studio palette (as a custom control).


The CheckedComboBox derives from ComboBox. In order to avoid the problem of the list portion disappearing before the user finishes the selection, I decided to catch the DropDown event and display my own list portion which consists of a Form whose client area is completely filled by a CheckListBox. Both the Form and the CheckListBox are my own custom versions since I needed to override some of the default behaviour.

Therefore, my custom list portion appears either on the DropDown event or when the user presses the Down arrow while the CheckedComboBox has the focus. I overrode the OnDropDown(), OnKeyDown(), and the OnKeyPress() methods to:

  1. display the dropdown list, and
  2. prevent any keyboard input, in order to make the text portion read-only.
protected override void OnDropDown(EventArgs e) {

private void DoDropDown() {
    if (!dropdown.Visible) {
        Rectangle rect = RectangleToScreen(this.ClientRectangle);
        dropdown.Location = new Point(rect.X, rect.Y + this.Size.Height);
        int count = dropdown.List.Items.Count;
        if (count > this.MaxDropDownItems) {
            count = this.MaxDropDownItems;
        } else if (count == 0) {
            count = 1;
        dropdown.Size = new Size(this.Size.Width, 
                       (dropdown.List.ItemHeight + 1) * count);

protected override void OnKeyDown(KeyEventArgs e) {
    if (e.KeyCode == Keys.Down) {        
    // Make sure that certain keys or combinations are not blocked.
    e.Handled = !e.Alt && !(e.KeyCode == Keys.Tab) &&
        !((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.Right) || 
    (e.KeyCode == Keys.Home) || (e.KeyCode == Keys.End));

protected override void OnKeyPress(KeyPressEventArgs e) {
    e.Handled = true;

Now, the list portion, being a Form, will stay open without being closed (hidden actually) until the user either presses Esc (the Escape button) to cancel any changes, Enter to accept all changes, or clicks with the mouse anywhere outside the list, which is the usual behaviour of the ComboBox.

In order to achieve this, I had to catch the Deactivate event of the Form (for the mouse click behaviour) and the keyboard events (for the Esc, Enter behaviour). In addition, if the user presses Del (the Delete button) or Shift + Del while the list portion has the focus, all items will be unchecked/checked, respectively, allowing a useful (to me, anyway :-)) keyboard shortcut. Note how a custom CCBoxEventArgs class has been used in order to distinguish whether the Deactivate message comes from the framework (i.e., the mouse click) or from the keyboard (to which I have control since I'm trapping keystrokes).

protected override void OnDeactivate(EventArgs e) {
    CCBoxEventArgs ce = e as CCBoxEventArgs;
    if (ce != null) {
    } else {


Using the Code

The code comes as a demo project which you can run and see as an example of usage. In order to use the CheckedComboBox in your code, you only need one file, CheckedComboBox.cs. Although I have not made it a fully-functional Visual Studio control with all the bows and whistles, once you compile your project, the CheckedComboBox should appear under the Components in your Visual Studio ToolBox palette and you can drag and drop it on to your Form in the Designer.

Alternatively, you can very easily use it by manually writing code like shown below to declare and create an instance of a CheckedComboBox:

private CheckedComboBox ccb = new CheckedComboBox();

// If more than 5 items, add a scroll bar to the dropdown.
ccb.MaxDropDownItems = 5;
// Make the "Name" property the one to display, rather than the ToString() 
// representation of the item.
ccb.DisplayMember = "Name";
// Set a separator for how the checked items will appear in the Text portion.
ccb.ValueSeparator = ", ";

In order to add items, use the Items collection...

private string[] coloursArr = { "Red", "Green", "Black", 
                                "White", "Orange", "Yellow", 
                                "Blue", "Maroon", "Pink", "Purple" };

for (int i = 0; i < coloursArr.Length; i++) {
    CCBoxItem item = new CCBoxItem(coloursArr[i], i);

... where the CCBoxItem is a simple test class I've created as follows (it's in the demo):

public class CCBoxItem {
    private int val;
    public int Value {
        get { return val; }
        set { val = value; }
    private string name;
    public string Name {
        get { return name; }
        set { name = value; }
    public CCBoxItem() {
    public CCBoxItem(string name, int val) { = name;
        this.val = val;
    public override string ToString() {
        return string.Format("name: '{0}', value: {1}", name, val);

You can also programmatically check an item or set its CheckState to Checked, Unchecked or Indeterminate. Note that the user cannot set an item state to Indeterminate from the User Interface, it can only be programmatically set (unless you want to handle the ItemCheck notification and add your own logic there).

// Check first item (index == 0)
ccb.SetItemChecked(0, true);
// Set the CheckState of the 2nd item in the list to Indeterminate.
ccb.SetItemCheckState(1, CheckState.Indeterminate);

The most interesting events you would probably be catching in your application are when the drop down portion closes (DropDownClosed) and when an item checked state is about to change (ItemCheck). You can register event handlers and handle the events as usual.

Note that the DropDownClosed event is available from the ComboBox directly, but the ItemCheck I had to make available from the CheckListBox.

// Add the handlers to the CheckedComboBox

this.ccb.DropDownClosed += new System.EventHandler(this.ccb_DropDownClosed);
ccb.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ccb_ItemCheck);

// Handler implementation

private void ccb_DropDownClosed(object sender, EventArgs e) {
    txtOut.AppendText(string.Format("value changed: {0}\r\n", ccb.ValueChanged));
    txtOut.AppendText(string.Format("value: {0}\r\n", ccb.Text));
    // Display all checked items.
    StringBuilder sb = new StringBuilder("Items checked: ");
    // Checked items can be found via the CheckedItems property.
    foreach (CCBoxItem item in ccb.CheckedItems) {
    sb.Remove(sb.Length-ccb.ValueSeparator.Length, ccb.ValueSeparator.Length);

private void ccb_ItemCheck(object sender, ItemCheckEventArgs e) {
    CCBoxItem item = ccb.Items[e.Index] as CCBoxItem;
    txtOut.AppendText(string.Format("Item '{0}' is about to be {1}\r\n", 
                                     item.Name, e.NewValue.ToString()));

In the code above, you can see that the checked items are available via the CheckedItems property. Similarly, CheckedIndices will return a collection of checked indices. Both these collections correspond to the .NET CheckedListBox collection, so nothing unfamiliar here.


In version 2.0, I have included some minor fixes/enhancements as follows:

  • Exposed the SetItemChecked(int index, bool isChecked) method so that you can programmatically set an item as checked
  • Relevant to the above, also included two more methods to get/set the CheckState:
    CheckState GetItemCheckState(int index)


    SetItemCheckState(int index, CheckState state)
  • Added a horizontal scrollbar to the dropdown list, which becomes visible if any of the items' length exceeds the width of the dropdownlist
  • Made the dropdown list "invisible" from the task bar (it used to appear because it is a Form)


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Stelios Alexandrakis
Software Developer (Senior)
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralRe: why does the first single-click seem to be swallowed? Pin
Stelios Alexandrakis4-Oct-11 23:32
memberStelios Alexandrakis4-Oct-11 23:32 
GeneralRe: why does the first single-click seem to be swallowed? Pin
ksanghavi@mantara.com13-Feb-12 9:16
memberksanghavi@mantara.com13-Feb-12 9:16 
GeneralRe: why does the first single-click seem to be swallowed? Pin
Member 799427313-Feb-12 18:21
memberMember 799427313-Feb-12 18:21 
GeneralRe: why does the first single-click seem to be swallowed? Pin
ksanghavi@mantara.com14-Feb-12 6:23
memberksanghavi@mantara.com14-Feb-12 6:23 
GeneralRe: why does the first single-click seem to be swallowed? Pin
Member 927891411-Jan-13 9:15
memberMember 927891411-Jan-13 9:15 
GeneralThanks Pin
quanvt13-Jan-11 16:50
memberquanvt13-Jan-11 16:50 
Generalthanks Pin
NoumanUllah Siddiqui1-Nov-10 14:37
memberNoumanUllah Siddiqui1-Nov-10 14:37 
GeneralA Very Simple Alternative Pin
hground13-Oct-10 9:41
memberhground13-Oct-10 9:41 
This is one of the articles that I looked at when I was searching for a way to conserve form space by creating a 4 checkbox drop down instead of spreading out the 4 check boxes on my form. I found a simpler solution and thought I would post it if anyone searching like I was could use it.

(NOTE: This is in VB, but should be easy to implement in C#.)

What I did was insert a single-column Listview onto my form with View set to Detail mode, MultiSelect set to True, and Checkboxes set to True. The following code will allow the list to drop down. Since I have multi-selection there is no need to display the selected value like you would do in a combo box so the drop-down appears to be a button to Show/Hide the list. In the code below I am dividing the height by 4 because my list is static and that is how many check boxes I have in my list. If you have a dynamic list then just read the number of items from the Listview and use that. You may have to play with it some to get the appearance that you want. Here are the events that I use:

Dim iListHt As Integer 'Set global variable to save height of list

        'Save initial height of list and then collapse it to a button
        iListHt = lvList.Height
        lvList.Height = CInt(iListHt / 4)
        lvList.Columns(0).Text = "Display List"

Private Sub lvList_ColumnClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles lvList.ColumnClick
    Dim iHt As Integer = lvList.Height
    If (iHt < iListHt) Then
        lvList.Height = iListHt
        lvList.Columns(0).Text = "Hide List"
        lvList.Height = CInt(iHt / 4)
        lvList.Columns(0).Text = "Display List"
    End If
End Sub

Private Sub lvList_ItemChecked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ItemCheckedEventArgs) Handles lvList.ItemChecked
    'Read values from list check boxes and update settings
End Sub

The ColumnClick event handles when they click on what looks like the Show/Hide List button and the ItemChecked event lets me handle anything that needs to respond to a change in the checkboxes. The value of each is read by accessing the "lvList.Items(iRowNum).Checked" value where iRowNum is the row you want to check. Hope this helps the next person that needs something like this.

GeneralDropDown do not show checked items Pin
Rui Frazao19-May-10 6:23
memberRui Frazao19-May-10 6:23 
GeneralDropDown Location Pin
Member 390701115-Feb-10 8:08
memberMember 390701115-Feb-10 8:08 
GeneralImplementation with multi rows Pin
platso_58814-Feb-10 18:10
memberplatso_58814-Feb-10 18:10 
GeneralRe: Implementation with multi Columns Pin
platso_58814-Feb-10 22:48
memberplatso_58814-Feb-10 22:48 
QuestionHow to Implementation this in framework 1.1 Pin
platso_58812-Feb-10 1:27
memberplatso_58812-Feb-10 1:27 
AnswerRe: How to Implementation this in framework 1.1 Pin
Stelios Alexandrakis12-Feb-10 1:44
memberStelios Alexandrakis12-Feb-10 1:44 
GeneralGreat Control ! What about DataSource Property. [modified] Pin
leftbox27-Nov-09 14:46
memberleftbox27-Nov-09 14:46 
GeneralRe: Great Control ! What about DataSource Property. Pin
santiagoitelgua21-Feb-11 5:39
membersantiagoitelgua21-Feb-11 5:39 
GeneralRe: Great Control ! What about DataSource Property. Pin
leftbox24-Feb-11 0:01
memberleftbox24-Feb-11 0:01 
GeneralGreat control. How to multi column, aggregate Pin
jjthebig19-Nov-09 5:21
memberjjthebig19-Nov-09 5:21 
GeneralRe: Great control. How to multi column, aggregate Pin
platso_58814-Feb-10 22:48
memberplatso_58814-Feb-10 22:48 
Generalsmall suggestion (DropDownWidth) Pin
Eddict16-Oct-09 0:15
memberEddict16-Oct-09 0:15 
GeneralRe: small suggestion (DropDownWidth) Pin
Stelios Alexandrakis16-Oct-09 0:52
memberStelios Alexandrakis16-Oct-09 0:52 
GeneralBug in GetItemChecked, SetItemChecked, GetItemCheckState, SetItemCheckState [modified] Pin
_virax21-Aug-09 4:53
member_virax21-Aug-09 4:53 
GeneralRe: Bug in GetItemChecked, SetItemChecked, GetItemCheckState, SetItemCheckState Pin
Stelios Alexandrakis22-Aug-09 2:46
memberStelios Alexandrakis22-Aug-09 2:46 
GeneralRe: Bug in GetItemChecked, SetItemChecked, GetItemCheckState, SetItemCheckState Pin
_virax24-Aug-09 3:48
member_virax24-Aug-09 3:48 
GeneralRe: Bug in GetItemChecked, SetItemChecked, GetItemCheckState, SetItemCheckState Pin
Stelios Alexandrakis24-Aug-09 5:49
memberStelios Alexandrakis24-Aug-09 5:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02-2016 | 2.8.180318.3 | Last Updated 22 Nov 2008
Article Copyright 2008 by Stelios Alexandrakis
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid