8

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

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

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

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 继承的类或制作用户控件来制作自定义列表。但是我不确定如何解决这个问题。关于使用继承/用户控件隐藏/覆盖清除方法的任何想法?它是否还需要隐藏/覆盖其他方法,或者有没有办法避免这种情况?

4

4 回答 4

7

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

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

于 2011-03-30T20:48:30.750 回答
3

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

于 2011-03-30T20:51:52.187 回答
1

可能是一个骇人听闻的解决方案,但这就是我的想法:

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

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

于 2011-04-12T21:53:50.430 回答
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;
        }
    }

}
于 2014-03-14T03:05:38.597 回答