CheckListBox.Items
属于 ObjectCollection
类型,这意味着它可以接受任何类型的 object
而不仅仅是 string
类型。默认情况下,CheckedListBox
将使用 ToString
方法的结果作为该项的文本。
这意味着,您可以编写一个代表存储在 CheckedListBox
中的项的 class
,该类会跟踪它们自己的 CheckedState
属性,并重写 ToString
方法以显示所需的文本。
public class CheckedListBoxItem
{
public string Text { get; set; }
public CheckState CheckState { get; set; } = CheckState.Unchecked;
public bool Checked
{
get
{
return (CheckState == CheckState.Checked || CheckState == CheckState.Indeterminate);
}
set
{
if (value)
{
CheckState = CheckState.Checked;
}
else
{
CheckState = CheckState.Unchecked;
}
}
}
public bool Contains(string str, StringComparison comparison)
{
return Text.IndexOf(str, comparison) >= 0;
}
public override string ToString()
{
return Text;
}
}
CheckedListBoxItem.Checked
的行为基于
CheckedListBox.GetItemChecked
,它将
CheckState.Interetminate
视为已选中,并且
CheckedListBox.SetItemChecked
将
true
视为
CheckState.Checked
,将
false
视为
CheckState.Unchecked
。
在您的
Form
中,您需要将
lstcollection
的类型更改为
List<CheckedListBoxItem>
,并将每个项目的
Text
属性设置为现在的字符串。
CheckedListBox
没有任何方法来绑定每个项目的
CheckState
,因此您必须自己管理。幸运的是,有一个
CheckedListBox.ItemChecked
事件,每当项目的选中状态发生变化时都会触发该事件。因此,您可以使用以下函数处理该事件...
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
CheckedListBoxItem item = checkedListBox1.Items[e.Index] as CheckedListBoxItem;
item.CheckState = e.NewValue;
}
您的筛选函数基本上没有变化,但是在将项添加到 CheckedListBox
时,您必须同时传递 CheckedState
...
private List<CheckedListBoxItem> liscollection;
private void textBox1_TextChanged(object sender, EventArgs e)
{
checkedListBox1.Items.Clear();
if (string.IsNullOrEmpty(textBox1.Text) == false)
{
foreach (var item in liscollection)
{
if (item.Contains(textBox1.Text, StringComparison.OrdinalIgnoreCase))
{
checkedListBox1.Items.Add(item, item.CheckState);
}
}
}
else
{
foreach (var item in liscollection)
{
checkedListBox1.Items.Add(item, item.CheckState);
}
}
}
编辑
对于这种情况,我不会在设计时将项目添加到checkedListBox1
中。相反,我会在运行时将它们添加到liscollection
,然后将liscollection
添加到checkedListBox1.Items
中。
public class YourForm : Form
{
public YourForm()
{
InitializeComponent();
liscollection = new List<CheckedListBoxItem>
{
new CheckedListBoxItem { Text = "The" },
new CheckedListBoxItem { Text = "needs" },
new CheckedListBoxItem { Text = "of" },
new CheckedListBoxItem { Text = "the" },
new CheckedListBoxItem { Text = "many" },
new CheckedListBoxItem { Text = "outweigh" },
new CheckedListBoxItem { Text = "the" },
new CheckedListBoxItem { Text = "needs" },
new CheckedListBoxItem { Text = "of" },
new CheckedListBoxItem { Text = "the" },
new CheckedListBoxItem { Text = "few" },
};
checkedListBox1.Items.AddRange(liscollection.ToArray());
}
}
如果你更喜欢从设计师中填充checkedListBox1
,那也可以。在调用checkedListBox1.Items.AddRange(...)
之前,你只需要在填充liscollection
后调用checkedListBox1.Items.Clear()
即可。
public class YourForm : Form
{
public YourForm()
{
InitializeComponent();
liscollection = new List<CheckedListBoxItem>();
foreach(string str in checkedListBox1.Items)
{
liscollection.Add(new CheckedListBoxItem { Text = str });
}
checkedListBox1.Items.Clear();
checkedListBox1.Items.AddRange(liscollection.ToArray());
}
}
重要的一行是
checkedListBox1.Items.AddRange(liscollection.ToArray())
。你需要将
Items
变为
CheckedListBoxItem
实例,这样在
ItemCheck
事件中可以将项目强制转换为
CheckedListBoxItem
的实例。通过从设计器填充
checkedListBox1
,您仅用
string
进行填充,因此在
ItemCheck
事件中尝试转换为
CheckedListBoxItem
时会失败。这就是为什么会出现
NullReferenceException
错误的原因。
Dictionary<string, bool>
来跟踪集合中每个项目的状态。假设您的字符串是唯一的。 - LarsTech