Удаление ListViewItem с изображением из ListView
Я пытаюсь динамически изменить ListView
в моей программе. Каждый предмет имеет ImageKey
и я использую SmallImageList
для них.
Проблема заключается в том, что всякий раз, когда я удаляю элемент, возникает проблема, которая была упомянута в этом вопросе:
До и после удаления элемента:
Используемый код:
// 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 ответа
К сожалению удаление Image
от ImageList
действительно вызывает индексы Items
двигаться вверх. Это означает, что внутренне Keys
больше не используются, но отображаются на индексы при добавлении или настройке, а затем больше не сохраняются.
Так что обойти можно либо..
Сохранить все
Images
вImageList
и жить с ненужнымImages
, В 256x256 пикселей x 4 байтаImage
может иметь только 256 КБ, поэтому трата памяти не будет такой большой. (Обратите внимание, что ресурсы 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; // (*)
Я думаю, что проблема в том, что вы пытаетесь изменить список в цикле foreach. Я бы рекомендовал сначала сделать цикл и запомнить выбранные элементы, которые вы хотите удалить, в новом списке, а затем в следующем цикле удалить их. Таким образом, вы не будете редактировать список, который вы зацикливаете.