0

I'm trying to make it so when the user types in the combobox, the combobox will try to find the first item that matches the search value completely. If thats not possible it will try to find the first one that contains the search value. If its neither of the before mentioned it will turn red. Now I have that part figured out and working, but the issue I have is that when the user would try to backspace the search will trigger again and thus it selects a row again most of the times. How can I make it that it won't search after a backspace, or prevent it from selecting the index if the user is trying to backspace. This is the code im using:

private void BestelIndexSearch(object sender, EventArgs e)
    {
        ComboBox Cmbbx = sender as ComboBox;
        int index = -1;
        string searchvalue = Cmbbx.Text;

        if (Cmbbx.Text != "")
        {
            for (int i = 0; i < Cmbbx.Items.Count; i++)//foreach replacement (not possible with combobox)
            {
                //search for identical art
                if (Cmbbx.Items[i].ToString().Equals(searchvalue))
                {
                    index = Cmbbx.Items.IndexOf(searchvalue);
                    break;//stop searching if it's found
                }
                //search for first art that contains search value
                else if (Cmbbx.Items[i].ToString().Contains(searchvalue) && index == -1)
                {
                    index = Cmbbx.FindString(searchvalue);
                    break;//stop searching if it's found
                }
            }
        }

        //if nothing found set color red
        if (index == -1)
        {
            Cmbbx.BackColor = Color.Red;
        }
        //if found set color white, select the item
        else
        {
            Cmbbx.BackColor = Color.White;
            Cmbbx.SelectedIndex = index;
        }
        //select text behind cursor 
        Cmbbx.SelectionStart = searchvalue.Length;
        Cmbbx.SelectionLength = Cmbbx.Text.Length - searchvalue.Length;
    }

The code is set to trigger on the TextChanged event and it is bound to multiple comboboxes. If anyone could help me it would be appriciated.

maam27
  • 444
  • 3
  • 21
  • so on backspace you dont want any search listed ? – Tharif Mar 27 '15 at 08:43
  • 1
    @utility at the moment when it works like this, if you typ something it will search and select the one you typed in or one that contains the same text at the beginning. it also selects the text behind the cursor so you can keep typing. but if you backspace it tries to find a item as well so if it finds one it simply fills the text again. so you would try to delete a part of the text and the search feature simply fills it back in again. so backspacing is currently doing near to nothing – maam27 Mar 27 '15 at 08:46
  • obviosuly it will match the content remaining after backspace know – Tharif Mar 27 '15 at 08:50
  • @utility I know it will match again and thus it fills in the item again and no progress has been made in removing part of the search value. thats why I've asked this question. I thought about possible options of solving this but I can't use a string to make it so it only tries to set the item to a diffrent one as before. And I don't know how I would go about using the keypress event to cancel the search, Since i'd rather not change it so when a key is pressed it runs this void instead of the `TextChanged` event. – maam27 Mar 27 '15 at 08:54
  • Just change the focus from the combobox if backspace is pressed – Tharif Mar 27 '15 at 09:01

2 Answers2

0

You should add a Keydown event to your combobox to check which key is pressed and modify your code with the following :

private bool _isCheckedActivated = true;

private void BestelIndexSearch(object sender, EventArgs e)
{
   if (! _isCheckedActivated)
   {
       _isCheckedActivated = true;
       return;
   }
   [...]
}

private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{

    if (e.KeyCode == Keys.Back)
        _isCheckedActivated = false;
}
  • I thought about using the `keypressed` event but I just couldn't think of a way that would cancel out the `TextChanged` event. EDIT: I tried your code and it works like I wanted it to, it's just missing delete but thats not a thing I can't add to this. Thanks for the help! – maam27 Mar 27 '15 at 08:56
  • Well, if you have a flag at the beginning of your TextChanged which checked if Backspace has been triggered and exit the method if so, it does exactly that. – Jean-Baptiste Raulin Mar 27 '15 at 09:05
  • I thought of using `TextChanged` event or using a string to see if it is even suggesting something else but I just couldn't think of a way to make it work. But the code change you suggested works fine, so thanks for that. – maam27 Mar 27 '15 at 09:08
0

Alternatively you can use the buildt in Autocomplete feature. With the buildt in feature you are less prone to bugs and the user can preview the alternatives before choosing an item. If you have more than one combobox you can create an extension-method.

public static class MyExtensions
{
    public static void SetDataAndAutoCompleteSource<T>(this ComboBox cmb, IEnumerable<T> src)
    {
        cmb.DataSource = src;
        cmb.AutoCompleteSource = AutoCompleteSource.ListItems;
        cmb.AutoCompleteMode = AutoCompleteMode.SuggestAppend;

        AutoCompleteStringCollection aSrc = new AutoCompleteStringCollection();
        aSrc.AddRange(src.Select(c => c.ToString()).ToArray());
        cmb.AutoCompleteCustomSource = aSrc;
    }

}

Usage:

comboBox1.SetDataAndAutoCompleteSource(myDataSource);
TDull
  • 753
  • 5
  • 12