[...]
After selecting 5 imagefiles, no thumbnails are displayed, although 5
images are available in the thumbnail image list.
Can you help me out?
As I alluded to in my previous reply, without a proper code example from
you, it's impossible to say exactly what things are wrong with your code.
There are things even about the code you did post that don't look quite
right to me, but out of context I can't say for sure anything is wrong.
That said, I decided to play a little bit with the virtual mode of the
ListView, and discovered a couple of important facts, one very pertinent
to your concern:
-- In virtual mode, assigning an ImageList item by key, rather than by
index, DOES NOT WORK!
-- The ImageList.ImageCollection class has a very poor key-mapping
implementation; it's a linear search!
Frankly, having looked at it a bit closer, I find the virtual mode of the
ListView class to be almost (but not completely) worthless. It has one
redeeming value: it allows for immediate display of the control,
populating the data structure only as the user scrolls through it.
But, the lack of a proper key-value access to the ImageList, both in terms
of it working at all, and in terms of performance, is a serious problem.
In addition, the class provides no way for you to know when you can
discard Image instances that are in the ImageList, which means that even
in virtual mode, you will eventually have to populate the ImageList with a
thumbnail for every single item in the list.
So over the long term -- i.e. the duration of the display using the
ListView -- virtual mode doesn't reduce your memory costs, and in fact if
the user eventually looks at every element, the memory cost increases
slightly due to the overhead of maintaining the virtual data structures.
I will grant that it does have that one redeeming value, and I admit
that's not an insignificant value. But I wish the class were more useful
than that. To me, "virtual" implies the ability to discard aged data, but
the most expensive data that will be associated with a ListViewItem -- its
thumbnail image -- can never be discarded once created.
Anyway, I've attached below the Form1.cs file for my little test
application. It doesn't handle caching, just the basic virtual mode
stuff. It bypasses the ImageList key-value mapping, using instead its own
Dictionary instance to maintain the mapping. I tested it with a
VirtualListSize of 10000, and performance is pretty good (and MUCH better
than when I used the key-value mapping of the ImageList...that is, using
the ContainsKey() and IndexOfKey() methods). Of course, the bitmaps I'm
using a very small.
This partial class works with the default Form1 template from VS2008, with
a single ListView instance named "listView1" added to it, and the
default-named handler for the ListView's RetrieveVirtualItem event (i.e.
the obvious configuration).
Hopefully with the code sample, you can easily see the approach needed to
work around the limitations in the ListView class.
Pete
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace TestVirtualListView
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
listView1.LargeImageList = new ImageList();
listView1.LargeImageList.ColorDepth = ColorDepth.Depth24Bit;
listView1.LargeImageList.ImageSize =
TextRenderer.MeasureText("10000", Font);
listView1.SmallImageList = listView1.LargeImageList;
}
private void listView1_RetrieveVirtualItem(object sender,
RetrieveVirtualItemEventArgs e)
{
e.Item = _LviItemForIndex(e.ItemIndex);
}
private Dictionary<string, int> _mpstriimage = new
Dictionary<string, int>();
private ListViewItem _LviItemForIndex(int i)
{
int iimage;
string strName = i.ToString();
ImageList.ImageCollection imgc =
listView1.LargeImageList.Images;
// Don't call the ImageList key-lookup methods, because they
are
// slow! Just maintain the key-to-image mapping ourselves.
if (!_mpstriimage.TryGetValue(strName, out iimage))
{
iimage = imgc.Count;
imgc.Add(_ImageForIndex(i));
_mpstriimage.Add(strName, iimage);
}
return new ListViewItem(strName, iimage);
}
private Image _ImageForIndex(int i)
{
Image imageRet =
new Bitmap(listView1.LargeImageList.ImageSize.Width,
listView1.LargeImageList.ImageSize.Height,
PixelFormat.Format24bppRgb);
using (Graphics gfx = Graphics.FromImage(imageRet))
{
gfx.Clear(this.ForeColor);
TextRenderer.DrawText(gfx, i.ToString(), Font,
new Rectangle(new Point(), imageRet.Size),
this.BackColor,
TextFormatFlags.HorizontalCenter);
}
return imageRet;
}
}
}