我试图在我的程序中动态更改ListView
。每个项目都有ImageKey
,我使用SmallImageList
。
问题是每当我删除某个项目时,this question中提到的问题就出现了:
删除项目之前和之后:
使用的代码:
// Add the images from an array of paths foreach (string xFile in files) { thumbnails_imageList.Images.Add(xFile, images[xFile]); files_lst.Items.Add(xFile, Path.GetFileNameWithoutExtension(xFile), xFile); } // Delete the selected key(s) foreach (ListViewItem xItem in files_lst.SelectedItems) { files_lst.Items.Remove(xItem); thumbnails_imageList.Images.RemoveByKey(xItem.Name); }
问题中的答案(建议不要从ImageList
删除图片)不符合我的要求,因为我在删除后添加了相同ImageKey
的项目,因此, Image
中的一个SmallImageList.Images
获得相同的ImageKey
,因此图片变得不一致。答案也忽略了明显的内存泄漏。
答案 0 :(得分:0)
我认为问题在于您尝试修改foreach循环中的列表。我建议首先创建一个循环并记住要在新列表中删除的SelectedItem,然后在下一个循环中删除它们。这样您就不会编辑正在循环的列表。
答案 1 :(得分:0)
不幸的是,从Image
删除ImageList
确实会导致Items
的索引向上移动。这意味着在内部Keys
不再使用,但在添加或设置时映射到索引,然后不再保持完整。
所以要解决方法,你可以......:
将所有Images
保留在ImageList
中,并使用不必要的Images
。在256x256像素x 4字节时,Image
只能有256k,因此内存浪费不会那么大。 (请注意,没有GDI +资源被浪费,因为ImageList
没有为其Images
创建任何句柄。)但是如果添加/删除ImageList
的增长大小,可能会变成问题..
或者您可以通过存储和重置ImageKeys
来解决。
以下是一个例子:
private void DeleteButton_Click(object sender, EventArgs e)
{
foreach (ListViewItem xItem in listView1.SelectedItems)
{
// maybe insert the loop below here (*)
listView1.Items.Remove(xItem);
// only delete when no longer in use:
string key = xItem.ImageKey;
if (listView1.Items.Cast<ListViewItem>().Count(x => x.ImageKey == key) == 0)
imageList1.Images.RemoveByKey(key);
}
// after deletions, restore the ImageKeys
// maybe add a check for Tag == null
foreach (ListViewItem xItem in listView1.Items)
xItem.ImageKey = xItem.Tag.ToString();
}
为此,您需要存储正确的密钥字符串。我选择在IListViewItem.Tag
属性中这样做。您可以在添加Items
之前或删除之前执行此操作:
foreach (ListViewItem xItem in listView1.Items)
xItem.Tag = xItem.ImageKey; // (*)