«SelectedIndexChanged» не запускается после «Items.Clear ()» в ListBox - PullRequest
8 голосов
/ 31 марта 2011

Для 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);
        }
    }
}

Edit: Я рассматриваю возможность создания собственного списка путем создания класса, который наследуется от ListBox, или создания пользовательского элемента управления. Однако я не уверен, как подойти к этому. Любые идеи о сокрытии / переопределении метода clear с использованием любого из наследования / userControl? Потребуется ли скрыть / переопределить другие методы, или есть способ избежать этого?

Ответы [ 4 ]

5 голосов
/ 31 марта 2011

Глядя на код в Reflector, метод Clear () для Items просто сбрасывает внутренний список объектов объекта .Net (и, как вы заметили, не запускает OnSelectedIndexChanged).

Свойство SelectedIndex возвращает -1, поскольку логика в получателе свойства требует, чтобы -1 возвращалось, если во внутреннем списке нет элементов.

2 голосов
/ 31 марта 2011

Clear () очищает только внутреннюю коллекцию элемента управления.Clear () не будет запускать событие SelectedIndexChanged, потому что это событие будет вызвано только изменением CurrentSelectedIndex.Попробуйте вместо этого использовать lst. ClearSelected ().Вызов этого метода эквивалентен установке свойства SelectedIndex в отрицательное значение (-1).Вы можете использовать этот метод, чтобы быстро отменить выбор всех элементов в списке.В качестве альтернативы вы можете попробовать вызвать Items.Clear () и затем вызвать ListBox. RefreshItems

1 голос
/ 13 апреля 2011

, вероятно, хакерское решение, но вот что я подумал:

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

возможно, это решит твою проблему.

0 голосов
/ 14 марта 2014

Это мой способ, он совместим с существующим кодом.

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

}
...