Click here to Skip to main content
13,004,839 members (65,337 online)
Click here to Skip to main content
Add your own
alternative version


31 bookmarked
Posted 11 Jul 2003

Build a Better CheckedListBox Control

, 11 Jul 2003
Rate this:
Please Sign up or sign in to vote.
This custom CheckedListBox control keeps users from changing the checkstate of items, fixes a TabControl bug, and adds extra functionality.


  • Control forgets checked status of items when using a TabControl.
  • Users are able to check or uncheck items.
  • Cannot reference an item based on its index.


All of these problems can be rectified by using a custom control.

Custom Control

The code below adds the AutoCheck property, the same property that the CheckBox control has, to the CheckedListBox control. It also implements a bug fix, plus allows to reference items in the control just like you can reference them in a ComboBox. To create our BetterCheckedListBox control, create a new VB.NET Class Library Project and copy the following code into Class1.vb.

'Show the CheckedListBox icon in the Toolbox for our component
<ToolboxBitmap(GetType(CheckedListBox))> _
Public Class BetterCheckedListBox
Inherits System.Windows.Forms.CheckedListBox
' Class level variables 
 Dim AllowChecks As Boolean 'Controls whether checkstate can be changed
 Dim ChkMember As String 'The DataColumn to use for checkstate
 Dim dt As DataTable 'Data to display
' Bug Fix
' When the CheckedListBox control is in a Tabcontrol 
' and that the Datasource property is used to fill
' up the item list, setting the clb's visible property
' to false, then to true, or flipping the tabs would
' cause the clb to "forget" the checks.
' Implement Carl Mercier's workaround
 Public Overloads Property DataSource() As Object
   'Return our datatable variable
   DataSource = CType(dt, Object)
  End Get
  Set(ByVal value As Object)
   'Set our datatable variable
   dt = CType(value, DataTable)
  End Set
 End Property
 Private Function LoadData()
  Dim bufAllowChecks = AllowChecks
  If AllowChecks = False Then
   'This is needed so we can change checkstates
    AllowChecks = True
  End If
  'Clear items
  'Fill it again
  Dim i As Integer
  For i = 0 To dt.DefaultView.Count - 1
   'Determine whether to check each item or not
   If dt.Rows(i).Item(ChkMember) = "1" Or _
     dt.Rows(i).Item(ChkMember) = "True" Then
    MyBase.Items.Add(dt.DefaultView.Item(i), True)
    MyBase.Items.Add(dt.DefaultView.Item(i), False)
   End If
  AllowChecks = bufAllowChecks
 End Function
 'Added or deleted records won't show without a refresh
 Public Overrides Sub Refresh()
 End Sub
' Allow / Lock Checkstate Functionality
' Only let users check or uncheck items when you let them. 
' Note that you can't programmatically check or uncheck
' items either unless AllowChecks is True.
' This is an emulation of the Checkbox control's AutoCheck
' property.
'Show our property under the Behavior section of the Properties window
'So that it can be set at design time
<System.ComponentModel.Description("Allow checkstate to be changed"), _
System.ComponentModel.Category("Behavior")> _
 Public Property AutoCheck() As Boolean
   'Return our checkstate variable
   AutoCheck = AllowChecks
  End Get
  Set(ByVal value As Boolean)
   'Set our checkstate variable
   AllowChecks = value
  End Set
 End Property
 'Override the ItemCheck event with our own
 Protected Overrides Sub OnItemCheck(ByVal ice As _
  'Allow checks to be changed only if AutoCheck = True
  If AllowChecks = False Then
   ice.NewValue = ice.CurrentValue
  End If
 End Sub
' Reference Item By It's Index Functionality
' Wouldn't it be nice if you could reference items in a
' CheckedListBox control just like you can with a 
' ComboBox? Well now you can!
' Obtain Checkstatus, Text, and Values via an items index
<System.ComponentModel.Description("Gets or sets the CheckMember")> _
 Public Property CheckMember() As String
   CheckMember = ChkMember
  End Get
  Set(ByVal value As String)
   ChkMember = value
  End Set
 End Property
<System.ComponentModel.Description("Gets or sets an items's checkstate")> _
 Public Property Checked(ByVal index As Integer) As Boolean
   'Search for the item in CheckedIndices to see if its checked or not
   If MyBase.CheckedIndices.IndexOf(index) <> -1 Then
    Checked = True
    Checked = False
   End If
  End Get
  Set(ByVal value As Boolean)
   'Set item's checkstate
   Dim bufAllowChecks = AllowChecks
   If AllowChecks = False Then
    AllowChecks = True
   End If
   MyBase.SetItemChecked(index, value)
   AllowChecks = bufAllowChecks
  End Set
 End Property
<System.ComponentModel.Description("Gets or sets an items's DisplayMember")> _
 Public Overloads Property Text(ByVal index As Integer) As String
   Text = dt.Rows(index).Item(MyBase.DisplayMember)
  End Get
  Set(ByVal value As String)
   dt.Rows(index).Item(MyBase.DisplayMember) = value
  End Set
 End Property
<System.ComponentModel.Description("Gets or sets an items's ValueMember")> _
 Public Property Value(ByVal index As Integer) As String
   Value = dt.Rows(index).Item(MyBase.ValueMember)
  End Get
  Set(ByVal value As String)
   dt.Rows(index).Item(MyBase.ValueMember) = value
  End Set
 End Property
End Class

Once this project is compiled, copy the output, BetterCheckedListBox.dll, to C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\PublicAssemblies\.

Then right click on the Toolbox, choose 'Add/Remove', select BetterCheckedListBox, and click OK to add our custom control to the Toolbox.

Demo Project

To create our demo project, start a new VB.NET Windows Application Project and copy the following code into Form1.vb. Run the project, a screen shot of the demo is also shown below.

Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
 Public Sub New()
 End Sub
 Protected Overloads Overrides Sub _
   Dispose(ByVal disposing As Boolean)
  If disposing Then
   If Not (components Is Nothing) Then
   End If
  End If
 End Sub
 Private components As System.ComponentModel.IContainer
 Friend WithEvents Button1 As System.Windows.Forms.Button
 Friend WithEvents BetterCheckedListBox1 As _
 Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
 Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
 Friend WithEvents Label1 As System.Windows.Forms.Label
 Friend WithEvents Label2 As System.Windows.Forms.Label
 Friend WithEvents Label3 As System.Windows.Forms.Label
 Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
 Friend WithEvents Label4 As System.Windows.Forms.Label
 Friend WithEvents TextBox3 As System.Windows.Forms.TextBox
 Private Sub InitializeComponent()
  Me.Button1 = New System.Windows.Forms.Button
  Me.BetterCheckedListBox1 = New _
  Me.CheckBox1 = New System.Windows.Forms.CheckBox
  Me.TextBox1 = New System.Windows.Forms.TextBox
  Me.Label1 = New System.Windows.Forms.Label
  Me.Label2 = New System.Windows.Forms.Label
  Me.Label3 = New System.Windows.Forms.Label
  Me.TextBox2 = New System.Windows.Forms.TextBox
  Me.Label4 = New System.Windows.Forms.Label
  Me.TextBox3 = New System.Windows.Forms.TextBox
  Me.Button1.Location = New System.Drawing.Point(24, 144)
  Me.Button1.Name = "Button1"
  Me.Button1.Size = New System.Drawing.Size(120, 23)
  Me.Button1.TabIndex = 2
  Me.Button1.Text = "Add New Person"
  Me.BetterCheckedListBox1.AutoCheck = True
  Me.BetterCheckedListBox1.CheckMember = Nothing
  Me.BetterCheckedListBox1.Location = New System.Drawing.Point(24, 24)
  Me.BetterCheckedListBox1.Name = "BetterCheckedListBox1"
  Me.BetterCheckedListBox1.Size = New System.Drawing.Size(120, 94)
  Me.BetterCheckedListBox1.TabIndex = 3
  Me.CheckBox1.Location = New System.Drawing.Point(24, 120)
  Me.CheckBox1.Name = "CheckBox1"
  Me.CheckBox1.Size = New System.Drawing.Size(120, 16)
  Me.CheckBox1.TabIndex = 5
  Me.CheckBox1.Text = "Lock CheckBoxes"
  Me.TextBox1.Location = New System.Drawing.Point(152, 24)
  Me.TextBox1.Name = "TextBox1"
  Me.TextBox1.TabIndex = 6
  Me.TextBox1.Text = ""
  Me.Label1.Location = New System.Drawing.Point(152, 8)
  Me.Label1.Name = "Label1"
  Me.Label1.Size = New System.Drawing.Size(100, 16)
  Me.Label1.TabIndex = 7
  Me.Label1.Text = "Checked:"
  Me.Label2.Location = New System.Drawing.Point(24, 8)
  Me.Label2.Name = "Label2"
  Me.Label2.Size = New System.Drawing.Size(100, 16)
  Me.Label2.TabIndex = 8
  Me.Label2.Text = "People:"
  Me.Label3.Location = New System.Drawing.Point(152, 56)
  Me.Label3.Name = "Label3"
  Me.Label3.Size = New System.Drawing.Size(100, 16)
  Me.Label3.TabIndex = 10
  Me.Label3.Text = "Text:"
  Me.TextBox2.Location = New System.Drawing.Point(152, 72)
  Me.TextBox2.Name = "TextBox2"
  Me.TextBox2.TabIndex = 9
  Me.TextBox2.Text = ""
  Me.Label4.Location = New System.Drawing.Point(152, 104)
  Me.Label4.Name = "Label4"
  Me.Label4.Size = New System.Drawing.Size(100, 16)
  Me.Label4.TabIndex = 12
  Me.Label4.Text = "Value:"
  Me.TextBox3.Location = New System.Drawing.Point(152, 120)
  Me.TextBox3.Name = "TextBox3"
  Me.TextBox3.TabIndex = 11
  Me.TextBox3.Text = ""
  Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
  Me.ClientSize = New System.Drawing.Size(272, 190)
  Me.Name = "Form1"
  Me.Text = "BetterCheckedListBox Demo"
 End Sub
#End Region
 Dim dt As New DataTable
 Private Sub Button1_Click(ByVal sender As System.Object,_
          ByVal e As System.EventArgs) Handles Button1.Click
  Dim dr As DataRow = dt.NewRow
  dr(0) = "Person " & BetterCheckedListBox1.Items.Count + 1
  dr(1) = "x"
  dr(2) = 0 'Checked is False
  'Force refresh in order to show changes
 End Sub
 Private Sub Form1_Load(ByVal sender As System.Object,_
       ByVal e As System.EventArgs) Handles MyBase.Load
  'Load some items
  dt.Columns.Add("txt", GetType(String))
  dt.Columns.Add("val", GetType(String))
  dt.Columns.Add("chk", GetType(String))
  Dim i As Integer
  For i = 1 To 5
   Dim dr As DataRow = dt.NewRow
   dr(0) = "Person " & i
   dr(1) = i
   dr(2) = "True"
  'Set DataBindings
  BetterCheckedListBox1.DisplayMember = "txt"
  BetterCheckedListBox1.ValueMember = "val"
  BetterCheckedListBox1.CheckMember = "chk"
  BetterCheckedListBox1.DataSource = dt
 End Sub
 Private Sub CheckBox1_CheckedChanged(ByVal sender As _
      System.Object, ByVal e As System.EventArgs) _
      Handles CheckBox1.CheckedChanged
  'Allow / Lock items
  BetterCheckedListBox1.AutoCheck = Not CheckBox1.Checked
 End Sub
 Private Sub BetterCheckedListBox1_SelectedIndexChanged(ByVal _
     sender As System.Object, ByVal e As _
     System.EventArgs) Handles _
  'Determine whether item is checked or not
  TextBox1.Text = BetterCheckedListBox1.Checked(BetterCheckedListBox1.SelectedIndex)
  TextBox2.Text = BetterCheckedListBox1.Text(BetterCheckedListBox1.SelectedIndex)
  TextBox3.Text = BetterCheckedListBox1.Value(BetterCheckedListBox1.SelectedIndex)
 End Sub
 Private Sub BetterCheckedListBox1_ItemCheck(ByVal _
        sender As Object, ByVal e As _
        System.Windows.Forms.ItemCheckEventArgs) _
        Handles BetterCheckedListBox1.ItemCheck
  TextBox1.Text = _
 End Sub
End Class

Demo Screenshot


Make sure the custom control created is strongly named. To do this, you must first generate a key file and tell the compiler to use it.

Generate a key file by running the following command at the Visual Studio Command Prompt:

sn -k C:\Better.snk

Then, add the following as the first line (under the Imports) in the AssemblyInfo.vb file of your Custom control project.

<Assembly: AssemblyKeyFileAttribute("Better.snk")>

That's it. The BetterCheckedListBox control can now be easily deployed to the Global Assembly Cache.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Trevor Kennedy
Web Developer
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionRadioCheckListBox Control?? Pin
Member 848950516-Nov-12 9:26
memberMember 848950516-Nov-12 9:26 
RantThis article is miscategorized. It contains no C# whatsoever. Pin
BooGhost22-Dec-09 12:42
memberBooGhost22-Dec-09 12:42 
GeneralSet checked items Pin
Tamtararamtam9-Dec-07 23:40
memberTamtararamtam9-Dec-07 23:40 
Questionhow to search the combobox Pin
..HuNTeR..23-Feb-07 9:01
member..HuNTeR..23-Feb-07 9:01 
GeneralDisallow Multiple CheckedItems Pin
TLWallace.NET11-May-06 8:12
memberTLWallace.NET11-May-06 8:12 
GeneralKey Cannot be null error Pin
tim_d14-Apr-05 10:27
membertim_d14-Apr-05 10:27 
GeneralCheckedListBox problem Pin
vrushaliD5-Jan-05 18:41
membervrushaliD5-Jan-05 18:41 
GeneralUsing Custom Classes?!! Pin
dcrane31-Aug-04 13:16
memberdcrane31-Aug-04 13:16 
GeneralRe: Using Custom Classes?!! Pin
j45mw20-Nov-06 7:45
memberj45mw20-Nov-06 7:45 
Generalevent ItemCheck is not fired Pin
patrikm25-Mar-04 22:23
memberpatrikm25-Mar-04 22:23 
QuestionWhat the heck is ToolboxBitmap?! Pin
nzmike17-Jul-03 16:16
membernzmike17-Jul-03 16:16 
AnswerRe: What the heck is ToolboxBitmap?! Pin
nzmike17-Jul-03 16:20
membernzmike17-Jul-03 16:20 
GeneralCredits Pin
Carl Mercier12-Jul-03 17:09
memberCarl Mercier12-Jul-03 17:09 

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
Web01 | 2.8.170627.1 | Last Updated 12 Jul 2003
Article Copyright 2003 by Trevor Kennedy
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid