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

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

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

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

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

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

可能是一个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(); 

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

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

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