0

私は次のようにListViewにアイテムを追加しています:

    private int AddThreadToListView(int threadNumber, string proxy, string query, string page, string links)
    {
        int index = 0;
        listView1.SuspendLayout();

        Invoke(new MethodInvoker(
                       delegate
                       {
                           string[] row1 = { proxy, query, page, links };
                           ListViewItem item = new ListViewItem();

                           listView1.Items.Add(threadNumber.ToString()).SubItems.AddRange(row1);
                           index = listView1.Items.Count - 1;
                       }
                       ));

        if ((listView1.Items.Count % 1000) == 0)
        {
            listView1.ResumeLayout();
            listView1.SuspendLayout();
        }

        listView1.ResumeLayout();
        return index;
    }

次に、アイテムのインデックスを追跡して、スレッド内から戻って更新できるようにします。(それはうまくいきます)。

ただし、問題は、これらのアイテムを削除し始めると、何らかの理由でインデックスが変更されることです。

これが私の更新と削除のメソッドです:

    private void UpdateThreadListView(int threadNumber, string proxy, string query, string page, string links)
    {
        Invoke(new MethodInvoker(
                       delegate
                       {
                           listView1.BeginUpdate();

                           ListViewItem itm = listView1.Items[threadNumber];
                           itm.SubItems[1].Text = proxy;

                           itm.SubItems[2].Text = query;
                           itm.SubItems[3].Text = page;
                           itm.SubItems[4].Text = links;                               

                           listView1.EndUpdate();

                       }
                       ));
    }

    private void RemoveThreadListView(int threadNumber)
    {
        Invoke(new MethodInvoker(
                       delegate
                       {
                           listView1.BeginUpdate();
                           listView1.Items[threadNumber].Remove();
                           listView1.EndUpdate();

                       }
                       ));
    }

どういうわけか、変更されないインデックス、作成されたリストビューアイテムごとに一意のインデックスが必要です。

どうすればこれを達成できますか?

4

3 に答える 3

1

Index自動的に管理されます。リスト内の特定のアイテムの場所を表すため、アイテムを削除すると、後続のすべてのアイテムの位置が変更されます。

TagプロパティをListViewItemキーとして使用して、他の基準を使用してアイテムを検索できます。例えば

private ListViewItem FindItem(object myTag)
{
    foreach(ListViewItem myItem in listView1.Items)
    {
        if (myItem.Tag.Equals(myTag))
            return myItem;
     }
     return null;
}

Tag任意のオブジェクトに設定できます。それは本質的にこの目的のためにあります(インデックス以外の手段によってノードを一意に識別します)。

O(n)これは(インデックス付けとは対照的に)最悪の場合であるため、インデックスを使用して要素を検索するよりも効率が悪いことに注意してくださいO(1)

編集:

上記の方法は、特定のタグが付いたアイテムを見つける方法の一例にすぎません。タグはいつでも設定できますが、一般的には、リストビューアイテムを作成するときに設定することをお勧めします。

    Invoke(new MethodInvoker(
                   delegate
                   {
                       string[] row1 = { proxy, query, page, links };
                       ListViewItem item = listView1.Items.Add(threadNumber.ToString());

                       item.SubItems.AddRange(row1);
                       item.Tag = threadNumber.ToString(); // or whatever you want to search by
                       index = listView1.Items.Count - 1;
                   }
                   ));

次に、上記の例で示したような実装FindItem()を行ったとすると、次のように実行できます。

var item = FindItem("3"); // returns the item tagged with "3"

この例では、スレッド#3のアイテムを返します。

于 2012-11-26T20:02:56.293 に答える
0

intthreadNumberをローカルintにコピーします

 private void UpdateThreadListView(int threadNumber, string proxy, string query, string page, string links)
    {
        int index = threadNumber;
        Invoke(new MethodInvoker(
                       delegate
                       {
                           listView1.BeginUpdate();

                           ListViewItem itm = listView1.Items[index];
etc..

理由を調べようとしています...

于 2012-11-26T19:59:24.680 に答える
0

ListViewItemsのインデックスが変更されるという事実は、インデックスがUIコントロール内のその場所にすぎないため、ListViewの適切な動作です。

ただし、アイテムを追跡したい場合は、インデックスを追跡することはお勧めしません。むしろ、ListViewItem自体を追跡します。

ListViewItemを直接参照できるようになったので、ListViewItemを操作するだけです。ListViewが更新されると、そのアイテムに加えられた変更が表示されます。

これが正しい方向にあなたを導くはずの簡単な例です。3行のListViewがあり、2番目の行が削除された後に最後の項目を更新したいとします。

//Grab a reference to the item that I want to update
ListViewItem lvi = this.lvwData.Items[2];

//Remove the second row
this.lvwData.Items.RemoveAt[1];

//Update the ListViewItem
lvi.Text = "Updated";

//Refresh the ListView
this.lvwData.Refresh();
于 2012-11-26T20:08:27.130 に答える