从ListView中删除带有图像的ListViewItem

时间:2016-10-07 11:52:01

标签: c# listview imagelist

我试图在我的程序中动态更改ListView。每个项目都有ImageKey,我使用SmallImageList

问题是每当我删除某个项目时,this question中提到的问题就出现了:

  

删除项目之前和之后:

     

Before After

     

使用的代码:

// 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,因此图片变得不一致。答案也忽略了明显的内存泄漏。

2 个答案:

答案 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;               // (*)