Winforms ComboBox SelectedItem changing does not affect the BindingSource

Revaz picture Revaz · Dec 12, 2011 · Viewed 9.7k times · Source

I am making C# / WinForms application. The problem I couldn't solve (yet) is that when I change the SelectedItem of ComboBox programatically, it is changed until the ComboBox loses the focus, after that it "reminds" its value before assigning the SelectedItem. I think that it takes the old value from binding source. When choosing an item using UI the underlying bound object is updated normally but it doesn't so when I'm assigning new value to SelectedItem programatically.

Just for additional info: I am trying to implement "undo", which means I am saving every change somewhere and when Edit>>>Undo I'm reversing all these changes done by user. Interesting thing is that the other controls (TextBoxes, NumericUpDowns) work fine.

Here are the Details:

I have a ComboBox which I bind to the ComboItem object like this:

ComboBox comboBox = new ComboBox();
List<ComboItem> items = new List<ComboItem>();
ComboList comboList = Configuration.ComboList.LoadComboList();

Combo myCombo = comboList.GetCombo(control.MemberName);
if (myCombo != null)
{
    items.Add(new ComboItem(0, "", 0.0, 0.0));
    for (int index = 0; index < myCombo.ComboItems.Count; index++)
    {
        items.Add(myCombo.ComboItems[index]);
    }
}

where Combo and ComboList are custom classes for loading the data from configuration file. Then I set the Display and Value members and also DataSource as well:

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Key";
comboBox.DataSource = items;

"Text" and "Key" are members of ComboItem class:

public class ComboItem
{
    public int Key { get; set; }
    public string Text { get; set; }
    public double Coef1 { get; set; }
    public double Coef2 { get; set; } 

    public void CopyValues() {...}
    public override bool Equals() {...}
}

Now the problem: when executing undo I check everything needed to have all the cast operations safe and clear and trying to "undo" with this code:

Logger.Info(controls[0], op, "ExecuteUndo");
((ComboBox)controls[0]).Focus();
((ComboBox)controls[0]).SelectedItem = (ComboItem)op.GetOldValue();
Logger.Info(controls[0], "AFTER CHANGE");

Logger is just logging. op object is taken from undo sequence and it gives appropriate value using "GetOldValue()". That code actually IS AFFECTING the UI, but until the control loses its focus. It happens on next undo which should affect other control and thus let this combobox to lose the focus.

I am sure that this happens on comboBox_LostFocus event because first thing I do on this event is Logging and it already shows me the value that SHOULDN'T BE.

Answer

LarsTech picture LarsTech · Dec 12, 2011

I think the problem you are seeing is that the ComboBox is displaying one value, but hasn't written the value to the binding source yet (which doesn't happen until you lose focus).

You can try doing something like this to write the data when an item is selected (assuming there is just the one databinding associated with the ComboBox):

private void comboBox_SelectedIndexChanged(object sender, EventArgs e) {
  comboBox.DataBindings[0].WriteValue();
}

And just to make sure, you either subscribe to this event from the designer, or wire it up manually:

public Form1() {
  InitializeComponent();
  comboBox.SelectedIndexChanged += comboBox_SelectedIndexChanged;
}