Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ComboBoxes are linked (and that is bad)

I am doing simple WinForms application, and I am facing some strange problem.

My form:

enter image description here

It is as easy as it can be: 3 comboboxes, and two buttons - OK and Cancel.

View:

private void applyOrderButton_Click(object sender, EventArgs e)
    {
        List<string> testList = new List<string>()
        {
            "A",
            "B",
            "C"
        };

        comboBox1st.DataSource = testList;
        comboBox2nd.DataSource = testList;
        comboBox3rd.DataSource = testList;

        comboBox1st.SelectedIndex = 2;
        comboBox2nd.SelectedIndex = 1;
        comboBox3rd.SelectedIndex = 0;
        //Presenter.DoTest();
    }

What happens after caling method applyOrderButton_Click() (it happens after Ok button is clicked) all of my comboBoxes change selected position. However, each of those comboBoxes have the same selected index - in this particular case it will be "A".

Then I change change comboBox selectedIndex using my cursour (for example I choose 3rd comboBox to show "C") the change is performed for all three comboBoxes. What I am doing wrong?

like image 796
bartosz.baczek Avatar asked Oct 28 '15 07:10

bartosz.baczek


2 Answers

You are running across something that is present in the background of WinForms called the "CurrencyManager".

Its job is to synchronize the "current record" across all bindable controls that refer to the same data source.

For instance, if you had added a label and bound it to the same list, and bound it so that it shows a property of one of the objects, it would always show the property value of the same object you had selected in the combobox.

One bonus of this is that you could easily add a form that edits a list of objects, binding textboxes and such to the properties of one of the objects and adding a navigator that allows you to move to the next or previous row. You would not have to manually ensure all textboxes refer to the correct object, the CurrencyManager would do all this for you.

However, in your case, since you bound the same data source to all three comboboxes, the CurrencyManager will ensure all three select the same row. If you select a new row in one of the comboboxes, the CurrencyManager will go and fix all the others to refer to the same row.

You can fix this in various ways:

  1. You can override the binding context for each combobox:

    comboBox2nd.BindingContext = new BindingContext();
    comboBox3rd.BindingContext = new BindingContext();
    

    Note that if you go this route you need to do this before assigning the SelectedIndex or SelectedItem properties, otherwise the CurrencyManager will have updated the other two comboboxes before you assigned new BindingContexts.

  2. You can assign distinct data sources to each combobox:

    combobox2nd.DataSource = testList.ToList();
    combobox3rd.DataSource = testList.ToList();
    
like image 120
Lasse V. Karlsen Avatar answered Sep 30 '22 04:09

Lasse V. Karlsen


Just assign new context to other ComboBoxes like that:

List<string> testList = new List<string>()
    {
        "A",
        "B",
        "C"
    };

comboBox1st.DataSource = testList;

comboBox2nd.BindingContext = new BindingContext();
comboBox2nd.DataSource = testList;

comboBox3rd.BindingContext = new BindingContext();
comboBox3rd.DataSource = testList;

comboBox1st.SelectedIndex = 2;
comboBox2nd.SelectedIndex = 1;
comboBox3rd.SelectedIndex = 0;

The CurrencyManager is used to keep data-bound controls synchronized with each other (showing data from the same record). The CurrencyManager object does this by managing a collection of the bound data supplied by a data source. For each data source associated with a Windows Form, the form maintains at least one CurrencyManager. Because there may be more than one data source associated with a form, the BindingContext object manages all of the CurrencyManager objects for any particular form. More broadly, all container controls have at least one BindingContext object to manage their CurrencyManagers.

like image 29
StepUp Avatar answered Sep 30 '22 04:09

StepUp