ListView在切换视图模式后不显示图像
本文关键字:显示 显示图 图像 模式 视图 ListView | 更新日期: 2023-09-27 17:57:48
当我在LargeIcon
以外的任何视图模式中将项目添加到ListView
时,当ListView
切换回LargeIcon
时,它将停止显示来自LargeImageList
的图像。这种情况一直持续到在LargeIcon
模式中将新项目添加到ListView
。
因此,以下顺序说明了问题:
- 创建
ListView
,添加列,将View
设置为Details
- 创建
ImageList
,设置ImageSize
,分配给ListView.LargeImageList
- 创建新的
ListViewItem
,设置其ImageKey
- 创建新图像,使用给定的密钥将其添加到
ImageList
- 将
ListViewItem
添加到ListView
- 将
ListView
模式切换到LargeIcon
- 不显示任何图像
- 重复步骤#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;
}
}
编辑:
对于任何会遭受同样问题的人。经过一些实验,至少有一个愚蠢的穷人的变通方法:
修改ImageList
,ListView
以某种方式检测到其更改并重新加载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 的答案中检查它们
解决您的问题
您可以通过使用ImageIndex
而不是ImageKey
来连接ListView
和ImageList
来避免这种情况。因此,在您的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
视图时,ImageIndex
是null
或-1
,ImageKey
被忽略。
关于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" ;
}