Bindable CheckedListBox






4.85/5 (17 votes)
In this article you will see how to bind a CheckedListBox to the data source and use features of multiple selection with data binding.
Introduction
It seems that the .NET CheckedListBox
even doesn't have primary binding facilities exists in the ListBox
and ComboBox
, because it must save multiple values in the database. Current article introducing an extended CheckedListBox
that has a single property for setting and getting checked items, and also has binding facilities.
Problems
- .NET
CheckedListBox
doesn't have binding facilities. - Because
CheckedListBox
works with an object collection it can't be bound to a data source. CheckedListBox
doesn't have a property representing whether item checked and it must be changed or getting data with Methods for one item or a collection of checked items hardly .
Needs
- Creating a public bindable property that representing checked items and sets checked items based on it.
- It must be one single property that when sets or gets it saves single primitive type value.
- Items must be loaded from a data source (it could be lookup table) different from Value data source.
- Because of list controls nature we must bind it to a column.
Using the code
A brief description of how to use the article or code. The class names, the methods and properties, any tricks or tips.
ExCheckedListBox
In the code samples major code belongs to ExCheckedListBox
inherited from CheckedListBox
of .NET framework.
It's extended CheckedListBox
control and has three extra properties:
1. Value
property:
This property is type of integer that brings ability to get and set checked item based on one single value. It works with bits in that integer, saves and retrieves values in single column.
get
{
///Gets checked items in decimal mode from binary mode
try
{
//each item in list has a number that is binary number in decimal mode
//this number represents that number
int poweredNumber = 1;
//loop in all items of list
for (int i = 0; i < this.Items.Count; i++)
{
//if item checked and the value doesn't contains poweredNumber
//then add poweredNumber to the value
if((this.GetItemChecked(i)))
this.value |= poweredNumber;
//else if poweredNumber exists in the value remove from it
else if ((this.value & poweredNumber) != 0)
this.value -= poweredNumber;
//raise to the power
poweredNumber *= 2;
}
}
catch (ArgumentException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
return this.value;
}
set
{
///sets checked items from binary mode converted from decimal value
this.value = value;
try
{
//each item in list has a number that is binary number in decimal mode
//this number represents that number
int poweredNumber = 1;
//loop in all items of list
for (int i = 0; i < this.Items.Count; i++)
{
//if poweredNumber exists in the value set checked on item
if ((this.value & poweredNumber) != 0)
this.SetItemCheckState(i, CheckState.Checked);
//else remove checked from item
else
this.SetItemCheckState(i, CheckState.Unchecked);
//raise to the power
poweredNumber *= 2;
}
}
catch (ArgumentException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
}
2. DataSource
property:
This property is type of object that brings ability to get and set data source like other collection controls (ListBox
and ComboBox
). In reality it's base DataSource
property used, but it hided in the .NET CheckedListBox
because of CheckedListBox
logic. So I hide it by new keyword and reused base DataSource
protected property.
/// <summary>
/// Gets or sets the data source for this CustomControls.CheckedListBox.
/// Returns:
/// An object that implements the System.Collections.IList or
// System.ComponentModel.IListSource
/// interfaces, such as a System.Data.DataSet or an System.Array. The
/// default is null.
///
///Exceptions:
/// System.ArgumentException:
/// The assigned value does not implement the System.Collections.IList or
// System.ComponentModel.IListSource
/// interfaces.
/// </summary>
[DefaultValue("")]
[AttributeProvider(typeof(IListSource))]
[RefreshProperties(RefreshProperties.All)]
[Browsable(true)]
public new object DataSource {
get
{
return base.DataSource;
}
set
{
base.DataSource = value;
}
}
3. DisplayMember
property:
This property is type of string that brings ability to get and set data source specific column like other collection controls (ListBox
and ComboBox
).
In reality it's base DisplayMember
property used, but it hided in the .NET CheckedListBox
because of CheckedListBox
logic.
So I hide it by new keyword and reused base DisplayMember
protected property.
/// <summary>
/// Gets or sets the property to display for this
/// CustomControls.CheckedListBox.
///
/// Returns:
/// A System.String specifying the name of an object property that is
/// contained in the collection specified by the
/// CustomControls.CheckedListBox.DataSource property. The default is
/// an empty string ("").
/// </summary>
[DefaultValue("")]
[TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter,
System.Design,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
[Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
typeof(UITypeEditor))]
[Browsable(true)]
public new string DisplayMember
{
get
{
return base.DisplayMember;
}
set
{
base.DisplayMember = value;
}
}
Demo Project
Demo project contains a SQL Script that creates two tables:
Products and Cities that have the same scenario of (presented products in specified cities).
Points of Interest
I wanted to implement another scenario (Questions and Answers) In that scenario we must navigate questions and answer the tests with multiple answers but there is a problem with data binding and this scenario.