tags:

views:

1406

answers:

3

I am using a listbox in my C#2.0 windows forms application. The method to populate the list box is

    private void PopulateListBox(ListBox lb, ReportColumnList reportColumnList)
    {
        lb.DataSource = reportColumnList.ReportColumns;
        lb.DisplayMember = "ColumnName";
        lb.ValueMember = "ColumnName";
    }

However, when it executes the method it also calls the SelectedIndexChanged event handler of the listbox, even though I am not setting the selected index in the method above. How can I prevent the SelectedIndexChanged event handler from being called for the above code?

I want the event to be called only when the user makes the selections in the ListBox. Or is there any other event which is only for user selecting listbox items using mouse click?

On another note, even if the user clicks on an empty area in the list box the SelectedIndexChanged event gets fired. So I am wondering how different is it from the MouseClick event?

+3  A: 

There are three ways you can go about this.

A) Don't hook into the SelectedIndexChanged event until AFTER you've called this method.

B) Have a private boolean in your class that's initially set to true. At the start of your PopulateListBoxmethod, set it to false, and at the end set it back to true. In your event handler for SelectedIndexChanged , if the flag is false, just return and do nothing.

C) In the start of your PopulateListBoxmethod, unhook from the event (this.listbox1.SelectedIndexChanged -= myMethod;) and then right before the method is done, rehook into that event.

BFree
Thanks for the answer. However, instead of the above steps, what if I use MouseClick event for handling the user selection changes? That way the MouseClick event will be fired only if user selection changes and won't get called when PopulateListBox() is called. Are there any drawbacks of using MouseClick event in this scenario? I tested it and it works fine, though I would like to know some hidden bugs I might face in the future due to this.
Rashmi Pandit
Can't use the MouseClick approach. Reason: For MultiExtended listbox, when the mouse click is fired, even if I have selected more than one item, the selected indices count does not reflect that. Only when the SelectedIndexChanged is called, I get a proper count.
Rashmi Pandit
I usually go with Option A. +1
Cerebrus
I cant use A because PopulateListBox() is being used by all listboxes on my page. Instead, I have used Kim's approach for populating and bool approach for some other reason.
Rashmi Pandit
A: 

You should be aware that even if you do not handle the event, the first item in the list will still be selected automatically when assigning the DataSource property. In order to force the user to make a selection you will need to unselect the automatically selected item.

If your SelectedIndexChanged event handler triggers some functionality when an item is selected you may still want to block this from being executed. One way to do that is to keep track of whether the code is currently populating the listbox or not. If the SelectedIndexChanged event is triggered while the listbox is being populated, you can avoid performing those actions:

private bool _populating = false;
private void PopulateListBox(ListBox lb, ReportColumnList reportColumnList)
{
    _populating = true;
    lb.DataSource = reportColumnList.ReportColumns;
    lb.DisplayMember = "ColumnName";
    lb.ValueMember = "ColumnName";

    // clear the automatically made selection
    lb.SelectedIndex = -1;
    _populating = false;
}

private void ListBox_SelectedIndexChanged(object sender, EventArgs e)
{
    if (!_populating)
    {
        // perform the action associated with selecting an item
    }

}
Fredrik Mörk
+2  A: 

You can populate the listbox using lb.Items.AddRange() instead of setting the datasource. In addition to not triggering the SelectedIndexChanged, this also won't pre-select the first item.

 lb.Items.Clear();
 lb.Items.AddRange(reportColumnList.ReportColumns.ToArray());
Kim Major
Yes ... thats exactly what I wanted. I changed my code as per your answer and it works like a charm :) Thanks a million, Kim!!!
Rashmi Pandit