ListView在切换视图模式后不显示图像

本文关键字:显示 显示图 图像 模式 视图 ListView | 更新日期: 2023-09-27 17:57:48

当我在LargeIcon以外的任何视图模式中将项目添加到ListView时,当ListView切换回LargeIcon时,它将停止显示来自LargeImageList的图像。这种情况一直持续到在LargeIcon模式中将新项目添加到ListView

因此,以下顺序说明了问题:

  1. 创建ListView,添加列,将View设置为Details
  2. 创建ImageList,设置ImageSize,分配给ListView.LargeImageList
  3. 创建新的ListViewItem,设置其ImageKey
  4. 创建新图像,使用给定的密钥将其添加到ImageList
  5. ListViewItem添加到ListView
  6. ListView模式切换到LargeIcon
    • 不显示任何图像
  7. 重复步骤#3-#6,现在处于LargeIcon模式
    • 所有图像均按预期显示

我还缺少什么

我尝试过以下内容:

  • 使ListView无效
  • 在添加项目之前/之后重新分配LargeImageList(甚至通过null

那些喜欢它而不是文字的人的测试代码:

public partial class Form1 : Form
{
    int       counter = 0;
    ImageList iList   = new ImageList();
    private string GetNewKey()
    {
        return counter++.ToString();
    }
    private Image GetNewImage(Size size)
    {
        var bmp = new Bitmap(size.Width, size.Height);
        using (var gra = Graphics.FromImage(bmp))
        {
            var rnd = new Random();
            var lines = rnd.Next(1000);
            for (int l = 0; l < lines; ++l)
            {
                var pen = new Pen(Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256)));
                var p1  = new Point(rnd.Next(size.Width), rnd.Next(size.Height)); 
                var p2  = new Point(rnd.Next(size.Width), rnd.Next(size.Height));
                gra.DrawLine(pen, p1, p2);
            }
        }
        return bmp;
    }
    public Form1()
    {
        InitializeComponent();
        iList.ImageSize         = new Size(100, 100);
        listView.LargeImageList = iList;
        listView.Columns.Add("name");
    }
    private void buttonAdd_Click(object sender, EventArgs e)
    {
        var key = GetNewKey();
        var lvi = new ListViewItem()
        {
            Name     = key,
            Text     = "blabla",
            ImageKey = key,
        };
        iList.Images.Add(key, GetNewImage(new Size(100, 100)));
        listView.Items.Add(lvi);
    }
    private void buttonClear_Click(object sender, EventArgs e)
    {
        listView.Items.Clear();
    }
    private void buttonLarge_Click(object sender, EventArgs e)
    {
        listView.View = View.LargeIcon;
    }
    private void buttonDetails_Click(object sender, EventArgs e)
    {
        listView.View = View.Details;
    }
}

编辑:

对于任何会遭受同样问题的人。经过一些实验,至少有一个愚蠢的穷人的变通方法:

修改ImageListListView以某种方式检测到其更改并重新加载LargeIcon模式的图像。问题是它是如何检测到变化的,以及为什么在模式变化后忽略ImageList。。。

    private void FixIt()
    {
        // Trigger a reload of the ListView.LargeImageList
        if (listView.View == View.LargeIcon)
        {
            var key = "Dummy image to be deleted right after its insertion...";
            iList.Images.Add(key, new Bitmap(1, 1));
            iList.Images.RemoveByKey(key);            
        }
    }

编辑#2:我还发现了ListView和相关组件的一些其他有趣功能。您可能想在问题4097912和问题23059678 的答案中检查它们

ListView在切换视图模式后不显示图像

解决您的问题

您可以通过使用ImageIndex而不是ImageKey来连接ListViewImageList来避免这种情况。因此,在您的buttonAdd_Click事件中使用:

  var lvi = new ListViewItem()
        {
            Name     = key,
            Text     = "blabla",
            //ImageKey = key,
            //Use ImageIndex and don't set both
            ImageIndex= Convert.ToInt32(key) //you could just use count++ 
        };

此问题背后的原因:

我不清楚这背后的原因,但我认为这可能是一个错误,从Details更改为LargeIcon时,默认情况下只检查ImageIndex,如果设置ImageKey,则ImageIndex将设置为-1。或者这可能是故意的,我不知道(请参阅下面的ImageKey部分),因为您没有SmallImageList,所以当更改为LargeIcon视图时,ImageIndexnull-1ImageKey被忽略。

关于ListViewItem.ImageIndex属性

ImageKey和ImageIndex属性是互斥的,这意味着如果设置了其中一个,则忽略另一个。此外,如果设置ImageKey属性,则ImageIndex属性将自动设置为-1。或者,如果设置ImageIndex属性,则ImageKey会自动设置为空字符串(")。

关于ListViewItem.ImageKey属性

如果您使用多个图像列表,对于带有ListView控件的小图标视图和大图标视图,您应该将图像的小版本和大版本放在它们各自的图像列表中的同一索引位置在视图之间切换时,一个列表中图像的索引位置用于定位另一个列表的图像,而不考虑指定的键值

这可以通过某种方式得到验证:

  • 使用现有代码(使用ImageKey
  • buttonLarge_Click事件处理程序中为listView中的任何Item设置ImageIndex将显示该项目的图像
  • buttonLarge_Click事件处理程序中的任何Item设置ImageKey将不会显示itme的图像

例如:

 private void buttonLarge_Click(object sender, EventArgs e)
        {
            listView.View = View.LargeIcon;
            //Set ImageIndex of Item 0 you could see its Icon.
            listView.Items[0].ImageIndex= 0 ;
            //set ImageKey will change nothing 
            //listView.Items[0].ImageKey= "0" ; 
        }