I have a CheckedListBox and a Text box. Goal here is to make a searchable CheckedListBox. When I type something in TextBox I have to filter items in CheckedListBox. I have written a below code to do so, But every time I enter a text the, CheckedListBox items gets cleared and new filtered items list will appear. The problem with this code is the filtering works fine but the checked items will be reset every time.
public partial class Form1 : Form
{
string[] elArray = {"Not Applicable" , "Aberdeen - Delivered" , "Belfast - Delivered" , "Birmingham - Delivered" , "Bournemouth - Delivered" , "Bradford - Delivered" , "Bristol - Delivered" , "Cambridge - Delivered" , "Canterbury - Delivered" , "OTHERS TO DE ADDED ..."};
public Form1()
{
InitializeComponent();
foreach (string elData in elArray)
{
resultBoxList.Items.Add(elData);
}
}
private void searchBox_TextChanged(object sender, EventArgs e)
{
resultBoxList.Items.Clear();
string[] resultArray = { };
foreach (string res in elArray)
{
if (res.Contains(searchBox.Text))
{
resultBoxList.Items.Add(res);
}
}
foreach (string resData in resultArray)
{
resultBoxList.Items.Add(resData);
}
}
}
You have two problems to resolve, to:
You can achieve that by using a DataTable as the data source of the list items and their checked states, and bind it's default DataView to the CheckedListBox.DataSource property.
Note |
---|
The DataSource , DisplayMember , and ValueMember properties of the CheckedListBox control are hidden. They don't show up in the Properties Window nor in IntelliSense.These properties are hidden and especially the DataSource because it delegates the functionalities of the DataManager to the base class, the ListBox which doesn't know about. Hence doesn't handle, the state of the CheckBoxes (i.e., it doesn't override OnDataSourceChanged() method to generate custom or specialized behavior. |
Firstly, create the DataTable, add the items, and populate the control.
public Form1()
{
InitializeComponent();
var elArray = new[]
{
"Not Applicable",
"Aberdeen - Delivered",
"Belfast - Delivered",
"Birmingham - Delivered",
"Bournemouth - Delivered",
"Bradford - Delivered",
"Bristol - Delivered",
"Cambridge - Delivered",
"Canterbury - Delivered",
"OTHERS TO DE ADDED ..."
};
var dt = new DataTable();
dt.Columns.Add("Item", typeof(string));
dt.Columns.Add("Checked", typeof(bool));
foreach (var item in elArray) dt.Rows.Add(item, false);
dt.AcceptChanges();
resultBoxList.DataSource = dt.DefaultView;
resultBoxList.DisplayMember = "Item";
resultBoxList.ValueMember = "Item";
// If not already done by the designer...
resultBoxList.ItemCheck += resultBoxList_ItemCheck;
}
Secondly, handle the ItemCheck event to update the checked state in the data source.
private void resultBoxList_ItemCheck(object sender, ItemCheckEventArgs e)
{
var dv = resultBoxList.DataSource as DataView;
var drv = dv[e.Index];
drv["Checked"] = e.NewValue == CheckState.Checked ? true : false;
}
Lastly, in the TextChanged
event, solve the above mentioned problems:
private void searchBox_TextChanged(object sender, EventArgs e)
{
var dv = resultBoxList.DataSource as DataView;
var filter = searchBox.Text.Trim().Length > 0
? $"Item LIKE '{searchBox.Text}*'"
: null;
dv.RowFilter = filter;
for (var i = 0; i < resultBoxList.Items.Count; i++)
{
var drv = resultBoxList.Items[i] as DataRowView;
var chk = Convert.ToBoolean(drv["Checked"]);
resultBoxList.SetItemChecked(i, chk);
}
}