How to prevent ListBox.SelectedIndexChanged event?
Asked Answered
S

7

21

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?

Sudoriferous answered 25/5, 2009 at 5:33 Comment(2)
For the most part, You can't prevent an object from raising an event.. You can only choose to stop listening for event notifications.Conservation
I meant if I could somehow prevent that part of my code, which fires the event. But as we can see there is nothing much I can do as all three lines in the PopulateListBox() are reqd :)Sudoriferous
B
18

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());
Brotherinlaw answered 25/5, 2009 at 7:3 Comment(1)
Yes ... thats exactly what I wanted. I changed my code as per your answer and it works like a charm :) Thanks a million, Kim!!!Sudoriferous
D
20

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.

Dieback answered 25/5, 2009 at 5:53 Comment(5)
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.Sudoriferous
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.Sudoriferous
I usually go with Option A. +1Genotype
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.Sudoriferous
@Rashmi: Not to mention that the mouse is not the only input device on a computer.Marathi
B
18

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());
Brotherinlaw answered 25/5, 2009 at 7:3 Comment(1)
Yes ... thats exactly what I wanted. I changed my code as per your answer and it works like a charm :) Thanks a million, Kim!!!Sudoriferous
R
9

There is a simplest answer to this problem: A Code snippet below can suggest the work around.

lstBxState.SelectionMode = SelectionMode.None;
lstBxState.DataSource = lstStates;
lstBxState.ValueMember = "StateId";
lstBxState.DisplayMember = "StateName";
lstBxState.ClearSelected();
lstBxState.SelectionMode = SelectionMode.One;

This means, just Make the Selection Mode as "None", and happily Data Bind the control. Then go ahead and change the mode to the required one (Here I have changed it to One, you may select Multiple too).

Robey answered 12/2, 2011 at 19:48 Comment(2)
'System.Web.UI.WebControls.ListSelectionMode' does not contain a definition for 'None'Haemostasis
This question is about Windows Forms, that namespace is for ASP.NET controls.Kreitman
F
2

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
    }

}
Fechter answered 25/5, 2009 at 6:18 Comment(0)
L
1

Inside the SelectedIndexChanged method, just pit in an if statement that says, if SelectedIndex == -1 do nothing else, do whatever you want to do in this method, probably not the most efficient code but worked for me :)

Loreeloreen answered 10/4, 2012 at 15:1 Comment(0)
U
0
private void PopulateListBox(ListBox lb, ReportColumnList reportColumnList)
{

    lb.SelectedIndexChanged -= this.*MethodnamewhichhandlesthisEvent*;  //unset eventhandler

    lb.DataSource = reportColumnList.ReportColumns;
    lb.DisplayMember = "ColumnName";
    lb.ValueMember = "ColumnName";

    lb.SelectedIndexChanged += this.*MethodnamewhichhandlesthisEvent*;  //set the eventhandler
}

Basically remove the delegate from the event and then add once you are done.

Ulcerate answered 11/4, 2012 at 4:12 Comment(0)
H
0

My situation might be unique, but I'll post it here just in case it helps someone.

I was doing the Items.AddRange to populate my ListBox instead of binding. I don't know why, but on PostBack, the SelectedIndex was going from -1 to 0. This might be because my ListBox was SelectionMode="Single".

My fix was to manually set the SelectedIndex to 0 instead of -1 after population:

listBox.Items.AddRange(items);
listBox.SelectedIndex = 0;
Haemostasis answered 1/8, 2012 at 18:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.