Need some help with adding filter to my ComboBox
drop down list(windows Forms Visual studio 2015)
The drop down is populated as per below:
public ReconciliationReport()
{
InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FindDLL;
this.sRootDirectory = Properties.Resources.sRootDirectory;
string[] arrProjectList = Directory.GetDirectories(sRootDirectory).Select(Directory => Path.GetFileName(Directory)).ToArray();
Array.Sort(arrProjectList);
int iProjectCount = arrProjectList.Length;
this.DropDownListSize = iProjectCount;
for (int i = 0; i < iProjectCount; i++)
{
SelectJobDropdown.Items.Add(arrProjectList[i]);
}
}
This gives me a nice drop down list of all current directories.
Now, I need to add a filer to show only items which contain a text typed into the ComboBox
itself regardless if the dropdown list itself is open or not.
I have disabled both AutoCompleteMode
and AutoCompleteSource
as it was not working as expected with the opened droped down list. It was opening additonal list on top the existing one but I could only select from the dropdown under it. See print screen below:
The list on top is inactive and I cannot select the text but also does not give an option to display substrings.
Only have one even for the box itself which is
private void SelectJobDropdown_SelectedIndexChanged(object sender, EventArgs e)
{
//Plenty of code here
}
Can someone point in the right direction how to filter the list as I type within the box itself.
Please NOTE I have been using C# for only 3 weeks so might get confused with some of the terminology or other aspects of this language etc.
I would suggest to use 2 Lists. 1 for the original values
List<string> arrProjectList;
public ReconciliationReport()
{
InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FindDLL;
this.sRootDirectory = Properties.Resources.sRootDirectory;
arrProjectList = Directory.GetDirectories(sRootDirectory).Select(Directory => Path.GetFileName(Directory)).ToList();
arrProjectList.Sort();
// then just bind it to the DataSource of the ComboBox
SelectJobDropdown.DataSource = arrProjectList;
// don't select automatically the first item
SelectJobDropdown.SelectedIndex = -1;
}
and 1 for the filtered values. In this example I use a TextBox
to catch the filter text. In the TextChanged
event take the filter text and pull out only those values from the original arrProjectList
List. You would need an extra option at the end to reset the binding to the old list if the filter is empty.
private void textBox1_TextChanged(object sender, EventArgs e)
{
string filter_param = textBox1.Text;
List<string> filteredItems = arrProjectList.FindAll(x => x.Contains(filter_param));
// another variant for filtering using StartsWith:
// List<string> filteredItems = arrProjectList.FindAll(x => x.StartsWith(filter_param));
comboBox1.DataSource = filteredItems;
// if all values removed, bind the original full list again
if (String.IsNullOrWhiteSpace(textBox1.Text))
{
comboBox1.DataSource = arrProjectList;
}
// this line will make sure, that the ComboBox opens itself to show the filtered results
}
EDIT
I found a Solution for typing the filter into the ComboBox
directly. The filtering is the same procedure, but using the TextUpdate
event it is necessary to unselect the SelectedIndex
which is automatically set to the first element after the binding. Then I guess you want to proceed to write your filter (more than just one letter), write the filter back into the ComboBox.Text
property and set the cursor position to the end:
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
string filter_param = comboBox1.Text;
List<string> filteredItems = arrProjectList.FindAll(x => x.Contains(filter_param));
// another variant for filtering using StartsWith:
// List<string> filteredItems = arrProjectList.FindAll(x => x.StartsWith(filter_param));
comboBox1.DataSource = filteredItems;
if (String.IsNullOrWhiteSpace(filter_param))
{
comboBox1.DataSource = arrProjectList;
}
comboBox1.DroppedDown = true;
// this will ensure that the drop down is as long as the list
comboBox1.IntegralHeight = true;
// remove automatically selected first item
comboBox1.SelectedIndex = -1;
comboBox1.Text = filter_param;
// set the position of the cursor
comboBox1.SelectionStart = filter_param.Length;
comboBox1.SelectionLength = 0;
}
Et voilà automatic filtering with a nice display and arrow selection afterwards.
EDIT 2
for case insensitive search you can use this:
List<string> filteredItems = arrProjectList.FindAll(x => x.ToLower().Contains(filter_param.ToLower()));
NOTE:
After the opening of the dropdownlist the cursor will disappear. To prevent this the Cursor.Current
has to be set to Cursor.Defualt
comboBox1.DroppedDown = true;
Cursor.Current = Cursors.Default;