【问题标题】:Removing ListViewItem with image from ListView从 ListView 中删除带有图像的 ListViewItem
【发布时间】:2016-10-07 11:52:01
【问题描述】:

我正在尝试在我的程序中动态更改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 的项目,因此在Images 中添加了多个SmallImageList.Images 得到相同的ImageKey,因此图像变得不一致。答案也忽略了明显的内存泄漏。

【问题讨论】:

    标签: c# listview imagelist


    【解决方案1】:

    不幸的是,从ImageList 中删除Image 确实会导致Items 的索引向上移动。这意味着在内部,Keys 不再使用,而是在添加或设置时映射到索引,然后不再保持原样。

    因此,您可以解决任何问题..:

    • 将所有Images 保留在ImageList 中,并使用不必要的Images。在 256x256pixels x 4 byte 时,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;               // (*)
    

    【讨论】:

    • 我不使用 ImageIndex 属性。正如我在问题中提到的那样,我已经使用了 ImageKey。
    • 哎呀抱歉。误读了问题。但是为什么你会得到重复呢???
    • 例如我删除了一个带有 ImageKey = "a" 的项目。然后在某个时候,我添加了一个带有 ImageKey =“a”的新项目。但是我为“a”添加了另一个图像,因此它们变得重复。
    • 是的,但为什么不使用唯一的名称呢?另外:在从 ImageList 中删除任何图像之前,您应该测试是否有任何项目仍在使用它!添加相同:在添加图像测试之前查看密钥是否已经存在然后递增..
    • 谢谢你,成功了。重新分配 ImageKeys 解决了这个问题。他们应该在 IMO 文档中提到这一点。
    【解决方案2】:

    我认为问题在于您尝试在 foreach 循环中修改列表。我建议首先创建一个循环并记住要在新列表中删除的 SelectedItems,然后在下一个循环中删除它们。这样您就不会编辑正在循环的列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多