问题
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
Imagesin theImageListand live with the unnecessaryImages. At 256x256pixels x 4 byte anImagecan have only 256k, so the memory waste will not be so big. (Note that no GDI+ resources are wasted, since anImageListdoesn't create any handles for itsImages.) But given enough adding/removing the growing size of theImageListmay 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
