ListViewItem的组未通过其他集合保留

时间:2012-09-18 12:16:52

标签: c# winforms listview .net-3.5

我正在尝试在自定义ListView中实现搜索功能,因此我隐藏Items一个自定义ObservableCollection,允许AddRange,类似于one defined on damonpayne.com(对于tl; dr-ers在那里基本上它会抑制触发OnCollectionChanged事件,同时添加多个项目然后使用NotifyCollectionChangedAction.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();

这个想法是,当项目不符合搜索条件时,它们将从base.Items(即 System.Windows.Forms.ListView )中删除,但仍保留在this.Items中(即 My.Name.Space.MyListView )。取消搜索或更改字词后,base.Items可以重新填充this.Items

除了一个小但重要的警告之外,这种方法很好并且符合预期:

问题在于ListViewItem s Group并非始终从this.Items传递到base.Items,因此所有项目都显示在“默认”组中。

关于为什么会发生这种情况以及如何解决问题的想法?

更新

我仍然坚持这一点。当然.ToArray()只是创建Items的浅表副本,以便保留Group? 这已由Maverik确认:

  

I just called in Linqpad, and while the list reference is different, you're right.. object references are same

更新2

好的,经过一些调查,我发现了它的发生地点。

ListViewItem添加到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 - 解决方案

see my answer

1 个答案:

答案 0 :(得分: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});

这些只是我之前为测试添加的一些临时项目,但设计师必须因某些原因记住它们。)


解决方案

解决方案如this SO answer中所述,我的代码现在为:

this.BeginUpdate();
base.Items.Clear();
base.Items.AddRange(this.Items.Select((ListViewItem)a => a.Clone()).ToArray());
this.EndUpdate();