【问题标题】:ListViewItem image not being shown on a virtual ListViewListViewItem 图像未显示在虚拟 ListView 上
【发布时间】:2018-04-16 00:29:56
【问题描述】:

我有一个 System.Windows.Forms.ListView。在正常(非虚拟)操作下,ListViewItems 的图像正确显示。但是,当我尝试将 ListView 转换为虚拟模式时,项目不再显示其图像。其他所有内容(文本、索引等)都按预期显示。

ListView 处于详细信息模式。 SmallImageList 设置正确。每个 ListViewItem 都正确设置了其 ImageKey。 ImageList 已正确填充。

为什么图像没有显示在虚拟 ListView 上? 如何确保图像按预期显示?

编辑:请查看以下代码作为演示我遇到的问题的示例。

static class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new VirtualListViewExample());
    }
}

class VirtualListViewExample : Form
{
    public VirtualListViewExample()
    {
        Image image = new Bitmap(16, 16);
        using (Graphics g = Graphics.FromImage(image))
        {
            g.FillRectangle(Brushes.Black, 0, 0, 16, 16);
        }

        ImageList imageList = new ImageList();
        imageList.ColorDepth = ColorDepth.Depth32Bit;
        imageList.ImageSize = new Size(16, 16);
        imageList.Images.Add("key", image);

        ListView normalList = new ListView();
        normalList.Columns.Add("Column");
        normalList.Dock = DockStyle.Fill;
        normalList.View = View.Details;
        normalList.VirtualMode = false;
        normalList.SmallImageList = imageList;
        for (int i = 0; i < 100; i++)
        {
            ListViewItem item = new ListViewItem();
            item.Text = "Item " + i.ToString();
            item.ImageKey = "key";
            normalList.Items.Add(item);
        }

        ListView virtualList = new ListView();
        virtualList.Columns.Add("Column");
        virtualList.Dock = DockStyle.Fill;
        virtualList.View = View.Details;
        virtualList.VirtualMode = true;
        virtualList.SmallImageList = imageList;
        virtualList.RetrieveVirtualItem += (s, e) =>
        {
            e.Item = new ListViewItem();
            e.Item.Text = "Item " + e.ItemIndex.ToString();
            e.Item.ImageKey = "key";
        };
        virtualList.VirtualListSize = 100;

        SplitContainer split = new SplitContainer();
        split.Dock = DockStyle.Fill;
        split.Panel1.Controls.Add(normalList);
        split.Panel2.Controls.Add(virtualList);
        this.Controls.Add(split);

        split.SplitterDistance = split.Width / 2;
    }
}

【问题讨论】:

标签: c# .net winforms listview


【解决方案1】:

我知道这是一个老问题,但为了有人寻找这个:

在虚拟模式下,item.ImageKey 将不起作用。请改用 item.ImageIndex。 ImageList.ImageCollection 有一个 IndexOfKey() 方法将键转换为索引。

    virtualList.RetrieveVirtualItem += (s, e) =>
    {
        e.Item = new ListViewItem();
        e.Item.Text = "Item " + e.ItemIndex.ToString();
        e.Item.ImageIndex = imagelist.Images.IndexOfKey("key");
    };

【讨论】:

    【解决方案2】:

    如果 ListView 控件和 ImageList 是 c'tor 的局部变量,这怎么能起作用?如果它们是 VirtualListViewExample 类的成员,效果会更好吗?

    更新:我上面的建议是完全错误的。有关此问题的解决方法,请参阅 duplicate question

    【讨论】:

    • 提供的代码只是一个简单示例来解释我的问题。它没有任何区别;为什么你认为它会?
    • 因为变量在 c'tor 完成后立即超出范围,甚至在它们映射的控件显示之前。如果它可以工作一点点,那纯粹是因为一次性物品和/或垃圾收集器的一些内部而幸运。首先要做的是在将这些变量转换为类成员以确保它们的生命周期正常后确认问题仍然存在。
    • 事实并非如此,仅供参考。不要挂断它。变量超出范围,但对象仍被引用。这与“纯粹的运气”无关。如果您将 GenerateMember 设置为 false,即使 Visual Studio 的表单设计器也会采用与我的示例相同的方式。无论如何,正如我所说,我的原始代码使用局部变量;问题中的代码只是复制问题的简单示例。
    • 糟糕!我的错!我今天学到了一些东西;-) 无论如何,您的问题是重复的(请参阅对您问题的评论中的参考)。我在那个问题中测试了解决方案,它似乎有效。
    猜你喜欢
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多