在下文中,“ListBox”不同于“listbox”,后者是用于ListBox 和CheckedListBox 的通用术语。
首先,绑定在testForm_Load 事件处理程序中完成。必须说明要绑定哪个对象以及要在列表框中显示什么属性/字段。
((ListBox)m_checkedListBox).DataSource = m_underList;
((ListBox)m_checkedListBox).DisplayMember = "PropToDisplay";
据我了解,绑定列表框的行为类似于只读单向(数据源 => 列表框)镜像视图。我们只能通过处理底层数据对象或控件的事件机制来影响列表框并检索其数据(忘记Items&co。)。
对于CheckListBox,我们可以通过在ItemCheck事件中添加ItemCheckEventHandler方法来检索选中的项目,然后将其存储到程序员定义的属性/字段的对象中。
m_checkedListBox.ItemCheck += new ItemCheckEventHandler(this.ItemCheck);
但我们无法定义数据源(基础列表)中内部检查项的状态以在CheckListBox 中显示为已检查。 CheckListBox 似乎不是为这种行为而设计的。
然后,可以通过底层列表随意添加或删除Userclass 对象或调用您想要的任何方法。只是不关心列表框。
m_underList.Add(new UserClass("Another example", 0, true));
最后,列表框的视图刷新。我看到很多文章都在谈论将 DataSource 设置为 null 然后将其重新分配回之前的对象。我寻找一种更好的方法来做到这一点(更好还是更漂亮?)。下面的方法很简单。
void refreshView(ListBox lb, object dataSource);
参考资料:
有关从列表框中检索用户选择的补充信息,请访问MSDN ListControl Class Examples
以下是CheckedListBox 被绑定、填充数据和清除的简单示例的完整代码。请注意,为了简单起见,我从列表框和数据列表都排序的原则开始。
UserClass.cs:用于存储显示/检查状态/隐藏数据的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestForm
{
class UserClass
{
private int m_underProp;
// ctors
public UserClass(string prop2Disp, int anotherObj, bool isChecked = false)
{
PropToDisplay = prop2Disp;
IsChecked = isChecked;
AnotherProp = anotherObj;
}
public UserClass()
{
PropToDisplay = string.Empty;
IsChecked = false;
AnotherProp = 0;
}
// Property to be displayed in the listbox
public string PropToDisplay
{
get;
set;
}
// For CheckedListBox only!
// Property used to store the check state of a listbox
// item when a user select it by clicking on his checkbox
public bool IsChecked
{
get;
set;
}
// Anything you want
public int AnotherProp
{
get
{
return m_underProp;
}
set
{
m_underProp = value;
// todo, processing...
}
}
// For monitoring
public string ShowVarState()
{
StringBuilder str = new StringBuilder();
str.AppendFormat("- PropToDisplay: {0}", PropToDisplay);
str.AppendLine();
str.AppendFormat("- IsChecked: {0}", IsChecked);
str.AppendLine();
str.AppendFormat("- AnotherProp: {0}", AnotherProp.ToString());
return str.ToString();
}
}
}
TestForm.Designer.cs:表单的设计
namespace TestForm
{
partial class testForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.m_checkedListBox = new System.Windows.Forms.CheckedListBox();
this.m_toggle = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// m_checkedListBox
//
this.m_checkedListBox.CheckOnClick = true;
this.m_checkedListBox.FormattingEnabled = true;
this.m_checkedListBox.Location = new System.Drawing.Point(13, 13);
this.m_checkedListBox.Name = "m_checkedListBox";
this.m_checkedListBox.Size = new System.Drawing.Size(171, 109);
this.m_checkedListBox.TabIndex = 0;
//
// m_toggle
//
this.m_toggle.Location = new System.Drawing.Point(190, 53);
this.m_toggle.Name = "m_toggle";
this.m_toggle.Size = new System.Drawing.Size(75, 23);
this.m_toggle.TabIndex = 1;
this.m_toggle.Text = "Fill";
this.m_toggle.UseVisualStyleBackColor = true;
this.m_toggle.Click += new System.EventHandler(this.m_toggle_Click);
//
// testForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(275, 135);
this.Controls.Add(this.m_toggle);
this.Controls.Add(this.m_checkedListBox);
this.Name = "testForm";
this.Text = "Form";
this.Load += new System.EventHandler(this.testForm_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.CheckedListBox m_checkedListBox;
private System.Windows.Forms.Button m_toggle;
}
}
TestForm.cs:表单的行为
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
namespace TestForm
{
public partial class testForm : Form
{
// a List which will contain our external data. Named as the underlying list
private List<UserClass> m_underList;
public testForm()
{
InitializeComponent();
m_underList = new List<UserClass> (3);
}
private void testForm_Load(object sender, EventArgs e)
{
// Bind the CheckedListBox with the List
// The DataSource property is hidden so cast the object back to ListBox
((ListBox)m_checkedListBox).DataSource = m_underList;
// Tell which property/field to display in the CheckedListBox
// The DisplayMember property is hidden so cast the object back to ListBox
((ListBox)m_checkedListBox).DisplayMember = "PropToDisplay";
/*
* The CheckedListBox is now in "read-only" mode, that means you can't add/remove/edit
* items from the listbox itself or edit the check states. You can't access
* the underlying list through the listbox. Considers it as a unidirectionnal mirror
* of the underlying list. The internal check state is disabled too, however
* the ItemCheck event is still raised...
*/
// Manually set the ItemCheck event to set user defined objects
m_checkedListBox.ItemCheck += new ItemCheckEventHandler(this.ItemCheck);
}
private void ItemCheck(object sender, ItemCheckEventArgs evnt)
{
if (sender == m_checkedListBox)
{
if (!m_checkedListBox.Sorted)
{
// Set internal object's flag to remember the checkbox state
m_underList[evnt.Index].IsChecked = (evnt.NewValue != CheckState.Unchecked);
// Monitoring
Debug.WriteLine(m_underList[evnt.Index].ShowVarState());
}
else
{
// If sorted... DIY
}
}
}
private void m_toggle_Click(object sender, EventArgs e)
{
if (sender == m_toggle)
{
if (m_toggle.Text == "Fill")
{
// Fill the checkedListBox with some data
// Populate the list with external data.
m_underList.Add(new UserClass("See? It works!", 42));
m_underList.Add(new UserClass("Another example", 0, true));
m_underList.Add(new UserClass("...", -7));
m_toggle.Text = "Clear";
}
else
{
// Empty the checkedListBox
m_underList.Clear();
m_toggle.Text = "Fill";
}
// Refresh view
// Remember CheckedListBox inherit from ListBox
refreshView(m_checkedListBox, m_underList);
}
}
// Magic piece of code which refresh the listbox view
void refreshView(ListBox lb, object dataSource)
{
CurrencyManager cm = (CurrencyManager)lb.BindingContext[dataSource];
cm.Refresh();
}
}
}
这是表单的视图。第一个图像是加载时的表单,第二个是单击“填充”按钮时的图像。可能会注意到,尽管IsChecked 属性在添加到数据源时设置为 true,但未选中列表框中的第二项。