5
votes

Background

Lately, I have observed two undesirable behaviors of the Winform ComboBox control:

  1. Setting the DataSource property to a new object sets the SelectedIndex value to 0
  2. Setting the DataSource property to a previously used object "remembers" the previously SelectedIndex value

Here is some sample code to illustrate this:

private void Form_Load(object sender, EventArgs e)
    {
        string[] list1 = new string[] { "A", "B", "C" };
        string[] list2 = new string[] { "D", "E", "F" };

        Debug.Print("Setting Data Source: list1");
        comboBox.DataSource = list1;

        Debug.Print("Setting SelectedIndex = 1");
        comboBox.SelectedIndex = 1;

        Debug.Print("Setting Data Source: list2");
        comboBox.DataSource = list2;

        Debug.Print("Setting SelectedIndex = 2");
        comboBox.SelectedIndex = 2;

        Debug.Print("Setting Data Source: list1");
        comboBox.DataSource = list1;

        this.Close();
    }

    private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        Debug.Print("Selected Index Changed, SelectedIndex: {0}", comboBox.SelectedIndex);
    }

    private void comboBox_DataSourceChanged(object sender, EventArgs e)
    {
        Debug.Print("Data Source Changed, SelectedIndex: {0}", comboBox.SelectedIndex);
    }

This produces the following output:

Setting Data Source: list1
Data Source Changed, SelectedIndex: -1
Selected Index Changed, SelectedIndex: 0
Setting SelectedIndex = 1
Selected Index Changed, SelectedIndex: 1
Setting Data Source: list2
Data Source Changed, SelectedIndex: 1
Selected Index Changed, SelectedIndex: 0
Setting SelectedIndex = 2
Selected Index Changed, SelectedIndex: 2
Setting Data Source: list1
Data Source Changed, SelectedIndex: 2
Selected Index Changed, SelectedIndex: 1

It is this last debug statement that is particularly interesting.

Questions

How is this possible and is there anyway to prevent this behavior?

Is the ComboBox's "memory" indefinite, or is it supported by objects which are susceptible to garbage collection? The former case means adjusting DataSource results in memory consumption, the latter case indicates the ComboBox's behavior is not predictable when setting the DataSource.

1
My guess would be that the ComboBox is keeping the associated CurrencyManager information, so that when you reconnect it, it can fetch the previous position. To "kill" it, try using comboBox.DataSource = new BindingSource(list1, null);LarsTech
@LarsTech, your suggestion does not work, but I do observe that setting the DataSource to a new BindingSource prevents the "Memory" from occuring (e.g. DataSource = new BindingSource { DataSource = list1 };. If you want to write that up as an answer, I'll probably accept it as a decent workaround. Still interested in knowing the underpinnings of the default behavior though...nicholas
The example in your comment and my example are essentially the same. Are you sure my example didn't work?LarsTech
I misunderstood. I thought you meant that by setting the DataSource to the new BindingSource inbetween the traditional assignments, it would fix it. Now I understand that you mean to always use BindingSource as the source. (Also, this approach lets you set a default value by setting the Position property: except -1 is not supported).nicholas

1 Answers

2
votes

I don't know all of the inner workings of the DataSource object, but it's probably the ComboBox keeping the associated CurrencyManager information for the list that allows it to remember the previous position when the DataSource gets reconnected.

You can avoid this behavior by wrapping the list inside a new BindingSource object:

comboBox.DataSource = new BindingSource(list1, null);

This will default the position property back to zero (if there are records).