Removing ListViewItem with image from ListView

不问归期 提交于 2019-12-25 08:19:51

问题


I'm trying to dynamically change a ListView in my program. Every item has an ImageKey and I use a SmallImageList for them.

The problem is whenever I delete an item, the problem which was mentioned in this question appears:

Before and after deleting an item:

Code used:

// 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);
}

The answer in the question (which recommends not to remove images from the ImageList) doesn't meet my requirements because I add items with the same ImageKey after removing, so, more than one Images in SmallImageList.Images get the same ImageKey, therefore images become inconsistent. Also the answer ignores the obvious memory leak.


回答1:


Unfortunately the removal of an Image from the ImageList indeed causes the indices of the Items to move up. This means that internally the Keys are no longer used but are mapped to the indices when adding or setting and then no longer kept intact.

So to workaround you can either..:

  • Keep all Images in the ImageList and live with the unnecessary Images. At 256x256pixels x 4 byte an Image can have only 256k, so the memory waste will not be so big. (Note that no GDI+ resources are wasted, since an ImageList doesn't create any handles for its Images.) But given enough adding/removing the growing size of the ImageList may become a problem..

  • Or you can work around by storing and resetting the ImageKeys.

Here is an example:

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();

}

For this to work you need to store the correct key strings. I chose to do so in the IListViewItem.Tag property. You can do it when adding the Items or right before the deleting:

foreach (ListViewItem xItem in listView1.Items)
        xItem.Tag = xItem.ImageKey;               // (*)



回答2:


I think the problem is that you try to modify list in the foreach loop. I would recommend first make a loop and remember the SelectedItems you want to delete in new list and then in the next loop delete them. This way you won't edit the list you are looping.



来源:https://stackoverflow.com/questions/39916598/removing-listviewitem-with-image-from-listview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!