CheckListBox.Items
имеет тип ObjectCollection
, что означает, что он будет принимать любые object
, а не только string
. По умолчанию CheckedListBox
будет отображать результаты ToString
в виде текста элемента.
Это означает, что вы можете написать class
для представления элементов, хранящихся в CheckedListBox
, которые отслеживают их владеть свойством CheckedState
, затем переопределить метод ToString
, чтобы он отображал нужный текст.
// CheckedListBoxItem.cs
public class CheckedListBoxItem
{
/// <summary>
/// The item's text - what will be displayed in the CheckedListBox.
/// </summary>
public string Text { get; set; }
/// <summary>
/// The item's check state.
/// </summary>
public CheckState CheckState { get; set; } = CheckState.Unchecked;
/// <summary>
/// Whether the item is checked or not.
/// </summary>
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)
{
// Since each item in the CheckedListBox is of type CheckedListBoxItem, we can
// just cast to that type...
CheckedListBoxItem item = checkedListBox1.Items[e.Index] as CheckedListBoxItem;
// Then set the checked state to the new value.
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();
// You would add one item to liscollection for each item that you have in the checkedListBox1's designer and set the Text to whatever the item is now...
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.Clear()
после заполнения liscollection
и до вызова checkedListBox1.Items.AddRange(...)
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
s, поэтому при попытке привести к CheckedListBoxItem
в событии ItemCheck
это не удается. Вот почему вы получаете это NullReferenceException
.