8

リストボックス(選択モードが1に設定されている)の場合、選択されたアイテムがあるかどうかを追跡したいと思います。そのために、SelectedIndexChangedにメソッドをサブスクライブし、SelectedIndexが-1であるかどうかを確認しました。ただし、SelectedIndexが-1に変更されても(まだ-1でない場合)、Items.Clear()を呼び出した後にイベントが発生しないことに気付きました。

なぜ発火しないのですか?リストをクリアする前に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から継承するクラスを作成するか、ユーザーコントロールを作成して、カスタムリストを作成することを検討しています。しかし、私はこれにどのようにアプローチするかわかりません。継承/userControlのいずれかを使用してclearメソッドを非表示/オーバーライドすることに関するアイデアはありますか?他のメソッドも非表示/オーバーライドする必要がありますか、それともこれを回避する方法はありますか?

4

4 に答える 4

7

Reflectorのコードを見ると、ItemsのClear()メソッドは、.Netオブジェクトの内部オブジェクトリストをリセットするだけです(お気づきのとおり、OnSelectedIndexChangedは起動しません)。

SelectedIndexプロパティは-1を返します。これは、プロパティのゲッターのロジックが、内部リストに項目がない場合は-1を返すように指示しているためです。

于 2011-03-30T20:48:30.750 に答える
3

Clear()は、コントロールの内部コレクションのみをクリアします。Clear()はSelectedIndexChangedイベントを発生させません。これは、そのイベントがCurrentlySelectedIndexを変更することによってのみ発生するためです。lstを使用してみてください。代わりにClearSelected()。このメソッドを呼び出すことは、SelectedIndexプロパティを負の値(-1)に設定することと同じです。この方法を使用すると、リスト内のすべてのアイテムの選択をすばやく解除できます。または、Items.Clear()を呼び出してから、ListBoxを呼び出すこともできます。RefreshItems

于 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 に答える