14

私はカスタムで検索機能を実装しようとしているので、 damonpayne.comで定義されているものと同様のカスタムを許可しListViewて隠しています(そこにあるtl; dr-ersの場合、基本的に追加中に発火イベントを抑制しますその後、複数のアイテムが)で起動します:ItemsObservableCollectionAddRangeOnCollectionChangedNotifyCollectionChangedAction.Reset

public new MyCollection<ListViewItem> Items { get; protected set; }

MyCollection_CollectionChanged()人口base.Items:_

this.BeginUpdate();
base.Items.Clear();
base.Items.AddRange(this.Items.ToArray());
this.EndUpdate();

アイテムが検索用語を満たさない場合、アイテムは(System.Windows.Forms.ListViewなど)から削除されbase.Itemsますthis.Items、 (My.Name.Space.MyListViewなど)には残ります。検索がキャンセルされた場合、または用語が変更された場合は、base.Itemsによって再入力できますthis.Items

これは正常に機能しますが、1つの小さいが重要な警告を除いて、期待どおりに機能します。

問題は、ListViewItems'Groupが一貫してからに運ばれておらずthis.Itemsbase.Itemsそのためすべてのアイテムがグループ「デフォルト」に表示されることです。

なぜこれが起こっているのか、そしてそれをどのように修正するのかについてのアイデアはありますか?

アップデート

私はまだこれに固執しています。確かにそれを行うと.ToArray()、の浅いコピーが作成されるItemsので、Group保存する必要がありますか?これはMaverikによって確認されています:

Linqpadで呼び出したところ、リスト参照は異なりますが、その通りです。オブジェクト参照は同じです。

アップデート2

さて、もう少し調査した後、私はそれがどこで起こっているのかを見つけました。

ListViewItemにsを追加する場合MyCollection<ListViewItem>

var item0 = new ListViewItem();
var item0.Group = this.Groups["foo"];
//here this.Items.Count = 0
this.Items.Add(item0); 
//here this.Items.Count = 1 with item0 having group "foo"

var item1 = new ListViewItem();
var item1.Group = this.Groups["bar"];
//here this.Items.Count = 1 with item0 having group "foo"
this.Items.Add(item1);
//here this.Items.Count = 2 with item0 having group "null" and item1 having group "bar"

MyCollection<また、これを通常に置き換えて確認しましたObservableCollection<が、同じことが引き続き発生します。

アップデート3-解決策

私の答えを見てください。

4

1 に答える 1

8

バックグラウンド

理解した!

理由はわかりませんが、本来あるべきときに例外がスローされていませんでした。

例外Cannot add or insert the item 'item0' in more than one place.がスローされるべきでした。

(からいくつかのものをクリアした後.designer.cs、それはスローされました(不思議なことに、ステップスルーしたときではありませんが...)

要求に応じて、カスタムを含むフォームの設計者からクリアされたコードListView

this.ListView.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
    listViewItem1,
    listViewItem2,
    listViewItem3,
    listViewItem4,
    listViewItem5,
    listViewItem6});

これらは私が以前にテストのために追加した一時的なアイテムでしたが、デザイナーは何らかの理由でそれらを覚えていたに違いありません。)


ソリューション

解決策はこのSOの回答で説明されているとおりであり、私のコードは次のようになります。

this.BeginUpdate();
base.Items.Clear();
base.Items.AddRange(this.Items.Select((ListViewItem)a => a.Clone()).ToArray());
this.EndUpdate();
于 2012-10-12T15:44:09.940 に答える