Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"SelectedIndexChanged" not firing after "Items.Clear()" in ListBox

For a ListBox (With Selection mode set to One), I wish to track whether there's a selected item or none selected. To do so, I subscribed a method to SelectedIndexChanged and checked if the SelectedIndex is -1 or not. However, I noticed that the event doesn't fire after calling Items.Clear(), even though SelectedIndex changes to -1 (if it wasn't already -1).

Why doesn't it fire? I know I can work around this by assigning -1 to SelectedIndex before clearing the list. But is there a better way?

Here's a simple code to replicate this:

using System;
using System.Windows.Forms;

namespace ns
{
    class Program
    {
        static ListBox lst = new ListBox();

        public static void Main()
        {
            lst.SelectedIndexChanged += new EventHandler(lst_SelectedIndexChanged);

            lst.Items.Add(1);

            Console.WriteLine("Setting selected index to 0...");
            lst.SelectedIndex = 0; //event fire here

            Console.WriteLine("(Selected Index == {0})", lst.SelectedIndex);

            Console.WriteLine("Clearing  all items...");
            lst.Items.Clear(); //event *should* fire here?!

            //proof that the selected index has changed
            Console.WriteLine("(Selected Index == {0})", lst.SelectedIndex);
        }

        static void lst_SelectedIndexChanged(object sender, EventArgs e)
        {
            Console.WriteLine("[!] Selected Index Changed:{0}", lst.SelectedIndex);
        }
    }
}

Edit: I am considering making a custom list by making a class that inherits from ListBox, or by making a user control. However I'm not sure how to approach this. Any ideas on hiding/overriding the clear method using either inheritance/userControl? Would it require hiding/overriding other methods as well or is there a way to avoid this?

like image 473
Shmuel Valariola Avatar asked Mar 30 '11 20:03

Shmuel Valariola


3 Answers

Looking at the code in Reflector, the Clear() method on Items just resets the .Net object's internal object list (and does not, as you noticed, fire OnSelectedIndexChanged).

The SelectedIndex property returns -1 because the logic in the property's getter dictates that -1 should be returned if there are no items in the internal list.

like image 197
dlev Avatar answered Oct 10 '22 00:10

dlev


Clear() only clears the internal collection of the control. Clear() won't fire the SelectedIndexChanged event because that event will only be raised by changing the CurrentlySelectedIndex. Try using lst.ClearSelected() instead. Calling this method is equivalent to setting the SelectedIndex property to negative one (-1). You can use this method to quickly unselect all items in the list. Alternatively you can try calling Items.Clear() and follow it with a call to ListBox.RefreshItems

like image 45
Mr. Young Avatar answered Oct 10 '22 00:10

Mr. Young


probably a hackish solution but this is what i thought of:

class myListBox
    {
        public ListBox myList;

        public myListBox()
        {
            myList = new ListBox();
        }

        public void listClear()
        {
            if (myList.Items.Count > 0)
            {
                myList.SelectedIndex = 0;
            }
            myList.Items.Clear();
        }

    }

than you can call this like this in your main form:

            myListBox example = new myListBox();
            example.myList.Items.Add("Example");
            example.myList.SelectedIndexChanged += new EventHandler(lst_SelectedIndexChanged);
            this.Controls.Add(example.myList);
            example.listClear();

maybe that could solve your problem.

like image 29
Eli Braginskiy Avatar answered Oct 10 '22 00:10

Eli Braginskiy