DonnieDarko
DonnieDarko

Reputation: 93

Winforms combobox bug - 2 items with the same value but different key

Is this truly a bug in Winforms in 2015 or am I just doing something wrong...

1) Create a new winforms project (.net 4.0) and add a combobox to the main form. 2) Use this for your form load code:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

    Dim items As New Dictionary(Of Integer, String)

    items.Add(1, "Value 1")
    items.Add(2, "Value 2")
    items.Add(3, "Value 3")
    items.Add(4, "Value 3")

    Dim dataSource As New BindingSource(items, Nothing)
    ComboBox1.DataSource = dataSource

    ComboBox1.DisplayMember = "Value"
    ComboBox1.ValueMember = "Key"

End Sub

Notice how items 3 & 4 have the same value, but different keys and that the display and value members are set correctly (unless I am going crazy, which is possible). When you run the application, open the combobox and select the last item. Now, open the combobox back up and you will notice that the 2nd to last item is now selected. That is a problem.

Any thoughts?

Thanks!

EDIT: I added an Infragistics UltraComboEditor to the form and placed the following code in the form load event:

    For Each item As KeyValuePair(Of Integer, String) In items
        UltraComboEditor1.Items.Add(New ValueListItem With {.DataValue = item.Key, .DisplayText = item.Value})
    Next

    UltraComboEditor1.SelectedIndex = 0
    UltraComboEditor1.AutoComplete = True

The Infragistics control allows me to autocomplete and enter my own text and it is not changing my selection when I select an item with the same text as the item above it. The Winforms control should not be changing my selection like that.

Upvotes: 1

Views: 2208

Answers (1)

Loathing
Loathing

Reputation: 5256

When the ComboBox allows the text portion to be edited, then it will pattern match and highlight the first prefix text that matches. This has the side effect that when the listbox is closed, the selected item is updated.

When the ComboBox's DropDownStyle == DropDownList mode, then the item previously selected will be highlighted in the dropdown list.

You can change the behavior by assigning a NativeWindow to the list window and then listen for the LB_SETCURSEL Msg.

You can use this thread as a starting point: Prevent AutoSelect behavior of a System.Window.Forms.ComboBox (C#)

Add an int index field to the Data object. Then in the Register method add:

    combo.SelectedIndexChanged += delegate {
        data.index = combo.SelectedIndex;
    };

Then pass the Data to the native window, which keeps track of the previously selected index.

private class NW : NativeWindow {
    Data data;
    public NW(IntPtr handle, Data data) {
        this.AssignHandle(handle);
        this.data = data;
    }

    private const int LB_FINDSTRING = 0x018F;
    private const int LB_FINDSTRINGEXACT = 0x01A2;
    private const int LB_SETCURSEL = 0x0186;

    protected override void WndProc(ref Message m) {
        if (m.Msg == LB_FINDSTRING)
            m.Msg = LB_FINDSTRINGEXACT;

        if (m.Msg == LB_SETCURSEL)
            m.WParam = (IntPtr) data.index;

        base.WndProc(ref m);
    }
}

Upvotes: 1

Related Questions