Override Winforms ComboBox Autocomplete Suggest Rule
autocomplete, c#, combobox, winforms
Solution
I've had the same problem and looked for a quick solution.
Eventually I ended up writing it myself. It's a little dirty but it should not be hard to make it prettier if needed.
The idea is to re-build the combo list after every key press. This way we can rely on the combo's built-in interface, and we don't need to implement our own interface with a textbox and a listbox...
Just remember to set `combo.Tag` to `null` if you re-build the combo's options list.
private void combo_KeyPress(object sender, KeyPressEventArgs e) {
comboKeyPressed();
}
private void combo_TextChanged(object sender, EventArgs e) {
if (combo.Text.Length == 0) comboKeyPressed();
}
private void comboKeyPressed() {
combo.DroppedDown = true;
object[] originalList = (object[])combo.Tag;
if (originalList == null) {
// backup original list
originalList = new object[combo.Items.Count];
combo.Items.CopyTo(originalList, 0);
combo.Tag = originalList;
}
// prepare list of matching items
string s = combo.Text.ToLower();
IEnumerable<object> newList = originalList;
if (s.Length > 0) {
newList = originalList.Where(item => item.ToString().ToLower().Contains(s));
}
// clear list (loop through it, otherwise the cursor would move to the beginning of the textbox...)
while (combo.Items.Count > 0) {
combo.Items.RemoveAt(0);
}
// re-set list
combo.Items.AddRange(newList.ToArray());
}
Problem
I'm trying to modify the behaviour of a Windows.Forms ComboBox so that the AutoComplete drop down displays items according to the rules I specify. By default, if you use AutoComplete in a ComboBox, the rule that's followed is "string s is included in the drop down if( s.StartsWith( userEnteredTextInTheComboBox) )" All I'm really interested in is substituting a new rule for the current one, but I can find no way to get at it. (Specifically, I'd prefer s.Contains instead of s.StartsWith.) I can kludge together a clumsy solution using two controls instead of one, but I'd really be happier with one that actually does what I want. Update: I found essentially the same question after some more searching. The answer supplied there suggests that using two controls to "fake it" is the way to go.