ListBox.SelectedIndexChanged not firing on first o

2019-07-26 03:08发布

问题:

This question already has an answer here:

  • “SelectedIndexChanged” not firing after “Items.Clear()” in ListBox 4 answers

I have a ListBox bound to a BindingList which is empty by default.
When the selected index changes it's supposed to update other controls with data from the selected object.
The problem is that the SelectedIndexChanged event is not firing on the first entry (index changing from -1 to 0).
It does fire however when I'm clicking on the first entry again (although index is not changing in this case) and when adding any more entries.
I checked the property myListBox.SelectedIndex and it does in fact change from -1 to 0 but for some reason doesn't call the event handler. Does anyone know why it's doing this and how to fix it?

Here's my code:

public partial class main : Form
{
    // The class of objects in my BindingList
    [Serializable]
    public class DisplayDefinition : INotifyPropertyChanged
    {
        private string _name;
        private int _width, _height, _posx, _posy;

        public string Name { get { return _name; } set { _name = value; NotifyPropertyChanged("Name"); } }
        public int Width { get { return _width; } set { _width = value; NotifyPropertyChanged("Width"); } }
        public int Height { get { return _height; } set { _height = value; NotifyPropertyChanged("Height"); } }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string s)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(s));
        }
    }

    // Defining the BindingList 
    BindingList<DisplayDefinition> displaydefinitions = new BindingList<DisplayDefinition>();

    // Binding the list to my listbox 
    public main()
    {
        InitializeComponent();
        listDisplays.DataSource = displaydefinitions;
        listDisplays.DisplayMember = "Name";
    }

    // Button adding a new object to the list
    private void btnNewDisplay_Click(object sender, EventArgs e)
    {
        DisplayDefinition d = new DisplayDefinition();
        displaydefinitions.Add(d);
        listDisplays.SelectedItem = d;
    }

    private void listDisplays_SelectedIndexChanged(object sender, EventArgs e)
    {
        DisplayDefinition d = (DisplayDefinition)listDisplays.SelectedItem;
        // Do something with "d" ...
    }
}

回答1:

The problem:

This behavior only occurs when using the ListBox with a data source, and doesn't occur when filling the ListBox manually.

The reason:

When adding the first item to the data source, the first item gets selected by default without firing the SelectedIndexChanged event (not sure why!) which seems to be a bug in ListBox, and that makes setting the SelectedItem or SelectedIndex property useless.

A solution (more like a workaround):

You can change the SelectedIndex property to a temporary index (-1) before setting the actual SelectedIndex/SelectedItem in order to trigger the SelectedIndexChanged event.

Something like the following should work:

// Button adding a new object to the list
private void btnNewDisplay_Click(object sender, EventArgs e)
{
    DisplayDefinition d = new DisplayDefinition();
    d.Name = "SomeName";
    displaydefinitions.Add(d);
    listDisplays.SelectedIndex = -1;
    listDisplays.SelectedItem = d;
}

private void listDisplays_SelectedIndexChanged(object sender, EventArgs e)
{
    if (listDisplays.SelectedIndex == -1) return;
    DisplayDefinition d = (DisplayDefinition)listDisplays.SelectedItem;
    // Do something with "d" ...
    Console.WriteLine(d.Name);
}

Hope that helps :)