Search code examples
c#visual-studiocombobox

ComboBox get selected value independently of selection method


Goal : Get selected value from ComboBox no matter if the user selected the value by clicking, pressing the enter key, pressing tab to autocomplete etc....

I have a dictionary<string, string[]> with key: ID and Value(s): version(s)

I have 2 ComboBoxes say CB1(containing keys\ID's) and CB2 as such :

enter image description here

When the user selects an ID(key) in CB1 the corresponding value(s) is filled CB2.

To do this I made use of the CB1_SelectionChangeCommited, CB1_Leave, CB1_KeyPressed methods. The later doesn't work properly as it doesn't detect key presses whatsoever. It's code is as follows

private void ComboBox3_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == 13)
        {
            if (comboBox3.Items.Contains($"{comboBox3.Text}"))
            {
                comboBox4.Items.Clear();
                comboBox4.Text = string.Empty;


                foreach (string version in dependenciesData.dependencyDic[Convert.ToString(comboBox3.Text)])
                {
                    comboBox4.Items.Add(version);
                }
                comboBox4.SelectedIndex = 0;
            }
        }
    }

Question :

- How can I fix the CB_Keypress method

OR

- Is there another way around to do what I want?


Solution

  • This works pretty well for me if I set the AutocompleteMode to Append or SuggestAppend and the AutoCompleteSource to ListItems:

    private void ComboBox3_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (dependenciesData.dependencyDic
               .TryGetValue((string)comboBox3.SelectedItem, out string[] values)) {
    
            comboBox4.DataSource = values;
            comboBox4.SelectedIndex = 0;
        }
    }
    

    Setting the AutocompleteMode to Suggest does not work.

    If it is ensured that the dictionary contains all combo box entries as key. Then this can be simplyfied a litte bit:

    if (comboBox3.SelectedIndex >= 0) {
        comboBox4.DataSource =
            dependenciesData.dependencyDic[(string)comboBox3.SelectedItem];
        comboBox4.SelectedIndex = 0;
    }
    

    I set the data source of comboBox3 like this:

    comboBox3.DataSource =dependenciesData.dependencyDic.Keys
        .OrderBy(x => x)
        .ToList();
    

    The easiest way to allow the user entering only allowed values is to set the DropDownStyle of combo box to DropDownList. With this setting, he cannot edit the combo box text anymore, however he still gets autocomplete suggestions.


    A few notes to your coding style:

    • Nested if-statements if (condition1) { if (condition2) { ... } } can be written as if (condition1 && condition2) { ... }.
    • Instead of adding individual items to a combo box with Items.Add(...), you can set the ComboBox.DataSource Property to a list or array.
    • If the combo box contains strings, you can simply cast the SelectedItem property to string instead converting it to string. (There is no conversion to be done since it is already a string that is statically typed as object).
    • You are testing whether the combo box items contain a text which is a O(n) operation. You can do this more efficiently by performing the test on the dictionary containing the same texts as keys, which is a O(1) operation.
    • You use the redundant string interpolation $"{comboBox3.Text}". Simply using comboBox3.Text yields the same result.