Reputation: 7963
I have a ComboBox
the DataSource
property is set to a List of this Type
:
public class ListInfo
{
public int Key { get; set; }
public string Name { get; set; }
}
The DropDownStyle
is set to DropDownList
, I set the AutoCompleteSource
to ListItems
and the AutoCompleteMode
to SuggestAppend
.
After some testing the client has come back and asked to be able to find any part of the text value, not just from the start of the text. Most examples that I have seen do this when the DropDownStyle
is set to DropDown
, I can't do that because the user cannot edit the contents of the list just select a value.
I have tried to create a CustomSource
, but when I try to set the AutoCompleteMode
to any value I get the following message:
Only the value AutoCompleteMode.None can be used when DropDownStyle is ComboBoxStyle.DropDownList and AutoCompleteSource is not AutoCompleteSource.ListItems.
I have found this AutoSuggestCombo, but again I hit the problem with the DropDownStyle
.
How can I either:
Use the ComboBox
with the DropDownStyle
set to DropDown
, that doesn't allow end user to enter new elements?
Be able to search any part of the String
value of the Items
, not just the StartsWith
that is currently used in the DropDownList
style?
Is this the opportunity to get started with Rx, or is that route a bloated solution and the learning curve that comes with it? (used simple tutorials so far)
Upvotes: 1
Views: 3606
Reputation: 54433
You must set all Autocompletion properties to none and handle the stuff yourself. There could be simpler solutions, but you can code the KeyPress event like this.
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
SortedDictionary<int, ListInfo> dict = new SortedDictionary<int, ListInfo>();
int found = -1;
int current = comboBox1.SelectedIndex;
// collect all items that match:
for (int i = 0; i < comboBox1.Items.Count; i++)
if (((ListInfo)comboBox1.Items[i]).Name.ToLower().IndexOf(e.KeyChar.ToString().ToLower()) >= 0)
// case sensitive version:
// if (((ListInfo)comboBox1.Items[i]).Name.IndexOf(e.KeyChar.ToString()) >= 0)
dict.Add(i, (ListInfo)comboBox1.Items[i]);
// find the one after the current position:
foreach (KeyValuePair<int, ListInfo> kv in dict)
if (kv.Key > current) { found = kv.Key; break; }
// or take the first one:
if (dict.Keys.Count > 0 && found < 0) found = dict.Keys.First();
if (found >= 0) comboBox1.SelectedIndex = found;
e.Handled = true;
}
You can decide if you want case sensitivity; probably not..
Upvotes: 2