1
votes

I have a combobox with DropDownStyle "DropDown". When I enter text the comboBox1.Text is not the text I see in text area of the comboBox and the SelectedIndex + SelectedItem does not correspond with the text inserted in my specific scenario.

It seems the selectedItem (+SelectedIndex) corresponds to the text when you open the dropdownlist and not when you close it.

Create a new form, place a combobox and a button on it. Add an eventhandler to the comboBox1 event for: - textchanged - dropdown - dropdownclosed and write the following properties of the combobox to the output window (or a textbox): - comboBox1.Text - comboBox1.SelectedIndex - comboBox1.SelectedItem - comboBox1.SelectedValue - comboBox1.FormattingEnabled I added an eventhandler for the click event of the button showing the comboBox1.Text as well.

Create a very simple class (e.g. TestItems) with 3 properties (a code, a description and a DescriptionUppercase). I tested it by filling the combobox items directly with instances of the TestItems class and by adding them first to a List and then setting the DataSource of the combobox to the List<>. It works a bit different, but both don't work the way I expect it to. I'll stick to the List. I fill the list with 100 testitems (Code="I0" .. "I99" and description "Item 1" .. Item 100"). I set the DisplayMember to "Description" and the ValueMember to "Code".

I insert three times the text "Item 578" using a slightly different scenario.

Scenario 1: SelectedIndex is -1 and SelectedItem is null. - just write "Item 578" in the combobox (don't open the dropdown) Logging from the output window:

TextChanged: ComboBox.Text = [ITEM 0] - ComboBox SelectedIndex = [0] - ComboBox SelectedItem = [I0 + Item 0] - ComboBox SelectedValue = [I0] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [I] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [It] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Ite] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item ] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 5] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 57] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 578] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True]

Scenario 2: selectedIndex = 0, SelectedItem is "Item 0" - Open the dropdownlist (click on the arrow at the right side of the combobox) - Enter "Item 578" - close the dropdownlist Logging:

TextChanged: ComboBox.Text = [ITEM 0] - ComboBox SelectedIndex = [0] - ComboBox SelectedItem = [I0 + Item 0] - ComboBox SelectedValue = [I0] - Combobox FormattingEnabled = [True] Dropdown opened: ComboBox.Text = [ITEM 0] - ComboBox SelectedIndex = [0] - ComboBox SelectedItem = [I0 + Item 0] - ComboBox SelectedValue = [I0] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [I] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [It] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Ite] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item ] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 5] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 57] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 578] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] DropDownClosed: ComboBox.Text = [Item 578] - ComboBox SelectedIndex = [0] - ComboBox SelectedItem = [I0 + Item 0] - ComboBox SelectedValue = [I0] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 578] - ComboBox SelectedIndex = [0] - ComboBox SelectedItem = [I0 + Item 0] - ComboBox SelectedValue = [I0] - Combobox FormattingEnabled = [True]

Scenario 3: SelectedIndex is 57 and SelectedItem is "Item 57" - Insert "Item 57" - Open the dropdownlist - Add an "8" to the end Logging:

TextChanged: ComboBox.Text = [ITEM 0] - ComboBox SelectedIndex = [0] - ComboBox SelectedItem = [I0 + Item 0] - ComboBox SelectedValue = [I0] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [I] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [It] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Ite] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item ] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 5] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [Item 57] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] Dropdown opened: ComboBox.Text = [Item 57] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [ITEM 578] - ComboBox SelectedIndex = [-1] - ComboBox SelectedItem = [] - ComboBox SelectedValue = [] - Combobox FormattingEnabled = [True] DropDownClosed: ComboBox.Text = [ITEM 578] - ComboBox SelectedIndex = [57] - ComboBox SelectedItem = [I57 + Item 57] - ComboBox SelectedValue = [I57] - Combobox FormattingEnabled = [True] TextChanged: ComboBox.Text = [ITEM 578] - ComboBox SelectedIndex = [57] - ComboBox SelectedItem = [I57 + Item 57] - ComboBox SelectedValue = [I57] - Combobox FormattingEnabled = [True]

Leaving the combobox (losing focus) doesn't change the SelectedItem. An additional remark: if you set the "FormattingEnabled" property of the combobox to false, then the combobox1.Text will be the text of the selectedItem (displaymember). So in the second scenario, you will see in the textarea of the combobox "Item 57", but when you click the button showing the combobox.Text it will say "Item 0".

The code to reproduce this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;

namespace TestCombobox
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.comboBox1.FormattingEnabled = true;
        comboBox1.DropDownClosed += ComboBox1_DropDownClosed;
        comboBox1.DropDown += ComboBox1_DropDown;
        comboBox1.TextChanged += ComboBox1_TextChanged;
        comboBox1.DisplayMember = "DescriptionUpperCase";
        comboBox1.ValueMember = "Code";
        FillCombo();
    }
    private void ComboBox1_DropDown(object sender, EventArgs e)
    {
        ShowDebugInfoCombobox("Dropdown opened");
    }

    private void ComboBox1_TextChanged(object sender, EventArgs e)
    {
        ShowDebugInfoCombobox("TextChanged");
    }

    private void ShowDebugInfoCombobox(string Info)
    {
        Debug.WriteLine($"{Info}: ComboBox.Text = <{comboBox1.Text}> - ComboBox SelectedIndex = <{comboBox1.SelectedIndex}> - ComboBox SelectedItem = <{comboBox1.SelectedItem}> - ComboBox SelectedValue = <{comboBox1.SelectedValue}>  - Combobox FormattingEnabled = <{comboBox1.FormattingEnabled}>");
    }

    private void ComboBox1_DropDownClosed(object sender, EventArgs e)
    {
        ShowDebugInfoCombobox("DropDownClosed");
    }

    private void FillCombo()
    {
        List<TestItems> aList = new List<TestItems>();
        for (int cnt = 0; cnt < 100; cnt++)
        {
            aList.Add(new TestItems($"I{cnt.ToString()}", $"Item {cnt.ToString()}"));
            //comboBox1.Items.Add(new TestItems($"I{cnt.ToString()}", $"Item {cnt.ToString()}"));
        }
        comboBox1.DataSource = aList;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(this.comboBox1?.SelectedItem?.ToString() + " Text = " + this.comboBox1.Text);

    }
}
public class TestItems
{
    public string Code { get; set; }
    public string Description { get; set; }
    public string DescriptionUpperCase { get { return Description.ToUpper(); }  }

    public TestItems(string code, string description)
    {
        this.Code = code;
        this.Description = description;
    }
    public override string ToString()
    {
        return this.Code + " + " + this.Description;
    }
}

}

Looks like a bug to me, not sure what your opinions are.

Kind regards, Bart

1

1 Answers

1
votes

First, that's a whole lot of extra info, which is why you haven't already gotten an answer. Second, if you want to "enter" text into a comboBox, you should use the KeyPress event and take the text from that, filtered by the enter key. Third, if you want to set the selected item to null if it isn't in the source data, you have to add conditional code to do that. This is a very simple example using a generic string list:

    List<string> source = new List<string>();

    public Form1()
    {
        InitializeComponent();
        source.Add("Item 1");
        source.Add("Item 2");
        comboBox1.Items.AddRange(source.ToArray());
    }

    // Enter key detection as shown in https://stackoverflow.com/a/1226740/4034168
    private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == 13)
        {
            if (!source.Contains(comboBox1.Text))
            {
                comboBox1.SelectedIndex = -1;
                comboBox1.SelectedItem = null;
            }
        }
    }

Also, if you want to prevent the user from being able to type any key (and yet still select from the drop down items), just use the TextUpdate event like this (add remove the KeyPress event since you wouldn't need it):

    private void comboBox1_TextUpdate(object sender, EventArgs e)
    {
        if (!source.Contains(comboBox1.Text)) comboBox1.SelectedItem = null;
    }