可绑定复选框列表






4.85/5 (17投票s)
本文将介绍如何将CheckedListBox绑定到数据源,以及如何使用数据绑定实现多选功能。
引言
看起来.NET 的CheckedListBox
甚至没有ListBox
和ComboBox
中存在的原生绑定功能,因为它必须在数据库中保存多个值。本文介绍了一个扩展的CheckedListBox
,它具有一个用于设置和获取选中项目的单个属性,并且具有绑定功能。
问题
- .NET 的
CheckedListBox
没有绑定功能。 - 因为
CheckedListBox
使用对象集合,所以它无法绑定到数据源。 CheckedListBox
没有表示项目是否选中的属性,必须通过方法来更改或获取单个项目或选中项目集合的数据,这很不方便。
需求
- 创建一个表示选中项目的公共可绑定属性,并根据该属性设置选中项目。
- 它必须是一个单一属性,在设置或获取时保存单个基元类型值。
- 项目必须从数据源(可能是查找表)加载,该数据源与值数据源不同。
- 由于列表控件的特性,我们必须将其绑定到一列。
使用代码
关于如何使用文章或代码的简要说明。类名、方法和属性,任何技巧或窍门。
ExCheckedListBox
在代码示例中,大部分代码属于从.NET框架的CheckedListBox
继承的ExCheckedListBox
。
这是一个扩展的CheckedListBox
控件,具有三个额外的属性
1. Value
属性
此属性的类型为整数,它能够基于单个值获取和设置选中项目。它使用整数中的位,在单个列中保存和检索值。
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
属性
此属性的类型为对象,它能够像其他集合控件(ListBox
和ComboBox
)一样获取和设置数据源。实际上,它使用了基DataSource
属性,但是由于CheckedListBox
的逻辑,它在.NET 的CheckedListBox
中被隐藏了。因此,我使用new关键字隐藏它并重用了基DataSource
受保护的属性。
/// <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
属性
此属性的类型为字符串,它能够像其他集合控件(ListBox
和ComboBox
)一样获取和设置数据源的特定列。
实际上,它使用了基DisplayMember
属性,但是由于CheckedListBox
的逻辑,它在.NET 的CheckedListBox
中被隐藏了。
因此,我使用new关键字隐藏它并重用了基DisplayMember
受保护的属性。
/// <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;
}
}
演示项目
演示项目包含一个SQL脚本,该脚本创建两个表
Products和Cities,它们具有相同的场景(在指定城市中展示的产品)。
关注点
我想实现另一个场景(问答)。在这个场景中,我们必须浏览问题并回答具有多个答案的测试,但是数据绑定在这个场景中存在问题。