“SelectedIndexChanged”在ListBox中的“Items.Clear()”之后没有触发

时间:2011-03-30 20:39:59

标签: c# winforms listbox selectedindexchanged

对于ListBox(选择模式设置为One),我希望跟踪是否选择了某个选定项目。为此,我订阅了一个方法到SelectedIndexChanged并检查SelectedIndex是否为-1。但是,我注意到在调用Items.Clear()之后事件不会触发,即使SelectedIndex更改为-1(如果它还不是-1)。

为什么不开火? 我知道我可以通过在清除列表之前为SelectedIndex分配-1来解决这个问题。但是有更好的方法吗?

这是一个复制它的简单代码:

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);
        }
    }
}

修改 我正在考虑通过创建一个继承自ListBox的类或通过创建用户控件来创建自定义列表。但是我不知道如何处理这个问题。 有关使用inheritance / userControl隐藏/覆盖clear方法的任何想法吗? 它是否需要隐藏/覆盖其他方法,还是有办法避免这种情况?

4 个答案:

答案 0 :(得分:5)

查看Reflector中的代码,Items上的Clear()方法只会重置.Net对象的内部对象列表(并且没有,如您所知,触发OnSelectedIndexChanged)。

SelectedIndex属性返回-1,因为属性的getter中的逻辑指示如果内部列表中没有项目,则应返回-1。

答案 1 :(得分:2)

Clear()仅清除控件的内部集合。 Clear()不会触发SelectedIndexChanged事件,因为只有通过更改CurrentlySelectedIndex才会引发该事件。尝试使用lst。ClearSelected()代替。调用此方法相当于将SelectedIndex属性设置为负一(-1)。您可以使用此方法快速取消选择列表中的所有项目。或者,您可以尝试调用Items.Clear()并通过调用ListBox来跟随它。RefreshItems

答案 2 :(得分:1)

可能是一个hackish解决方案,但这是我想到的:

class myListBox
    {
        public ListBox myList;

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

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

    }

你可以在主表单中这样称呼它:

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

也许这可以解决你的问题。

答案 3 :(得分:0)

这是我的方式,它与现有代码兼容。

public class DetailsListView : ListView
{
    public new class ListViewItemCollection : ListView.ListViewItemCollection
    {
        private DetailsListView m_owner;
        public ListViewItemCollection(DetailsListView owner)
            : base(owner)
        {
            m_owner = owner;
        }

        public override void Clear()
        {
            base.Clear();
            m_owner.FireChanged();
        }
    }

    private void FireChanged()
    {
        base.OnSelectedIndexChanged(EventArgs.Empty);
    }


    private ListViewItemCollection m_Items;

    public DetailsListView()
    {
        m_Items = new ListViewItemCollection(this);

        View = View.Details;
        GridLines = true;
        HideSelection = false;
        FullRowSelect = true;
    }

    public new ListViewItemCollection Items
    {
        get
        {
            return m_Items;
        }
    }

}