Graviton
Graviton

Reputation: 83264

How to get ComboBox.SelectedItem to bind when SelectedIndex is changed?

In my application, I will need to update a certain image when the selection of my combobox changes. Currently I do this by capturing the SelectedIndexChanged event and update the image there.

I have been trying another approach to do it, namely, using Binding in order to simplify my code, but it doesn't work.

Because the binding of ComboBox.SelectedItem to a certain property only applies after the ComboBox loses focus or when another control gains focus-- not when or before the SelectedIndexChanged event is fired.

How to get the binding to apply immediately when the SelectedItem or the SelectedIndex is changed?

This is my code:

public partial class Form1 : Form
{

    private readonly Person person;
    public Form1()
    {
        InitializeComponent();

        person = new Person()
        {
            Name = "joe",
            Race = Race.Indian
        };



        textBox1.DataBindings.Clear();
        textBox1.DataBindings.Add(nameof(textBox1.Text), person, nameof(person.Name));

        comboBox1.DataSource = Enum.GetValues(typeof(Race));
        comboBox1.DataBindings.Clear();
        comboBox1.DataBindings.Add(nameof(comboBox1.SelectedItem), person, nameof(person.Race));
        comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged;

    }

    private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
       //when selected index is changed, the data is lagging behind the selected item. 
       //eg: SelectedItem is already Chinese, but person.Race is still Indian
        MessageBox.Show($"data {person.Race}, selected item {comboBox1.SelectedItem}"); 
    }

    private int count = 0;

    private void button1_Click(object sender, EventArgs e)
    {
        person.Race =(Race)(((int)person.Race + 1) % Enum.GetValues(typeof(Race)).Length);
        person.Name = person.Name + $"{count++}";
    }
}

public enum Race
{
    Indian,
    Chinese,
    Causacian,
    Arabian,
    Jewish,
    SouthINdian,
}
public class Person: INotifyPropertyChanged
{
    private Race _race;
    private string _name;
    public string Name
    {
        get
        {
            return _name;

        }
        set
        {
            _name = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
        }
    }
    public Race Race
    {
        get
        {
            return _race;
        }
        set
        {
            _race = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs (nameof(Race)));

        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

}

Upvotes: 3

Views: 881

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125247

To solve the problem, you can bind to SelectedValue property:

comboBox1.DataSource = Enum.GetValues(typeof(Race)).Cast<Race>()
    .Select(x => new { Value = x, Display = x.ToString() })
    .ToList();
comboBox1.DisplayMember = "Display";
comboBox1.ValueMember = "Value";
comboBox1.DataBindings.Add(nameof(comboBox1.SelectedValue), person, nameof(person.Race),
    true, DataSourceUpdateMode.OnPropertyChanged);

Upvotes: 4

Related Questions