Search code examples
c#winformslistboxincremental-search

C# WinForms ListBox Incremental Search with Key/Value Pairs as ListItems


I've searched for an answer, and whilst there is one that works when using a listbox with items of type string, I can't figure out how to convert when my items are of type

KeyValuePair<string, ChangeRec>

I want to be able to search as I type in the listbox (cannot use ComboBox as the control needs to be a specific size on the form), searching by the key (Text) item. Thanks to @Marcel Popescu for the starting point. Here's my version of the code (have commented only above the line where it fails, as it rightly can't cast a kvp item as string):

private string searchString;
private DateTime lastKeyPressTime;

private void lbElementNames_KeyPress(object sender, KeyPressEventArgs e)
{
    this.IncrementalSearch(e.KeyChar);
    e.Handled = true;
}

private void IncrementalSearch(char ch)
{
    if ((DateTime.Now - this.lastKeyPressTime) > new TimeSpan(0, 0, 1))
    {
        this.searchString = ch.ToString();
    }
    else
    {
        this.searchString += ch;
    }
    this.lastKeyPressTime = DateTime.Now;
    //* code falls over HERE *//
    var item =
        this.lbElementNames.Items.Cast<string>()
            .FirstOrDefault(it => it.StartsWith(this.searchString, true, CultureInfo.InvariantCulture));

    if (item == null) return;
    var index = this.lbElementNames.Items.IndexOf(item);
    if (index < 0) return;        
    this.lbElementNames.SelectedIndex = index;
}

Solution

  • Use this, I am assuming it is the Key of KeyValuePair that you want to search in:

    //* code falls over HERE *//
    
    var item =
            this.lbElementNames.Items.Cast<KeyValuePair<string, ChangeRec>>()
                .FirstOrDefault(it => it.Key.StartsWith(this.searchString, true, CultureInfo.InvariantCulture));
    
    if (item.Equals(default(KeyValuePair<string, ChangeRec>))) return;
    

    As KeyValuePair is a value type, it can't ever be null. To find out whether it has been assigned a value, we check by using item.Equals(default(KeyValuePair<string, ChangeRec>))