简体   繁体   中英

Strange behavior while removing image from ListView

I have a ListView which I populate with the contents of an ImageList. When an Item is selected from the list, I check if the file still exists. If it doesn't, I want to remove it both from the Image List (which is private static) and from the ListView. For some strange reason, which I can't figure out, after removing the selected image from the list, the image right after it disappears and the last image in the list appears twice. For example, if the list held the following images: IMG1, IMG2, IMG3, IMG4, IMG5 and I remove IMG2 the new list will look like this: IMG1, IMG4, IMG5, IMG5 .

Furthermore, if I select the second image from the list (which is now IMG4 ) and display it in some picture control, IMG3 , which was supposed to be in that place will be displayed in the control.

Any ideas what's going on here?

EDIT: Populating the List view:

private static ImageList stampsImages

        if (stampsImages == null)
        {
            stampsImages = new ImageList();
            stampsImages.ImageSize = new Size(125, 75);
        }

        DirectoryInfo di = new DirectoryInfo(Globals.Directory);
        if (di.Exists)
        {
            FileInfo[] dFiles = di.GetFiles("*.png");
            int stampListSize = stampsImages.Images.Count;

            for (int i = 0; i < dFiles.Length; i++)
            {
                int idx = stampsImages.Images.IndexOfKey(dFiles[i].FullName);

                if (idx < 0)
                {
                    stampsImages.Images.Add(Bitmap.FromFile(dFiles[i].FullName));
                    stampsImages.Images[stampListSize].Tag = dFiles[i].FullName; 
                    stampsImages.Images.SetKeyName(stampListSize, dFiles[i].FullName);
                    stampListSize++;
                }
            }
        }
        else di.Create();

        for (int i = 0; i < stampsImages.Images.Count; i++)
        {
            ListViewItem stmp = new ListViewItem("", i);
            lvwStamps.Items.Add(stmp);
        }
        lvwStamps.LargeImageList = stampsImages;      

Checking if the file still exists:

    private bool IsStampAvailable(int listIdx)
    {
        bool stampExists = true;
        string stampFile = stampsImages.Images.Keys[listIdx];
        if (!File.Exists(stampFile))
        {
            lvwStamps.Items.RemoveAt(listIdx);
            stampsImages.Images.RemoveAt(listIdx);
            stampExists = false;
        }

        return stampExists;
    }

Every time you remove an image from the ImageList, you'll have to decrement the ImageIndex of each ListViewItem that points to an ImageIndex equal or higher than the ImageIndex of the deleted image. Usually a linear decrement is sufficient starting at the index of the Item after deleted Item (if ImageList and ListViewItems keep a 1:1 relation):

for (int i = lvItem.Index + 1; i < listView1.Items.Count; i++)
    listView1.Items[i].ImageIndex--;

Maybe more important is to delete the items AFTER reindexing (after deleting a ListViewItem the ListView must repaint and indicies should be in the right order for this):

int iImageIndex = lvItem.ImageIndex;
int iIndex = lvItem.Index; 
for (int i = iIndex + 1; i < listView1.Items.Count; i++) // correct the image indicies
    listView1.Items[i].ImageIndex--;       
lvItem.Remove(); // repaint
Image img = ImageList1.Images[iImageIndex];
ImageList1.Images.RemoveAt(iImageIndex);
img.Dispose();

The problem is that the ListView items probably remember the index of the image in the ImageList. If you remove an image from the ImageList, the ListView items will point to a wrong image.

Try to reference the images by key instead of by index.


This is a test I made

imageList1.Images.Add("img0", Properties.Resources.img0); // Use key as first argument.
imageList1.Images.Add("img1", Properties.Resources.img1);
imageList1.Images.Add("img2", Properties.Resources.img2);
imageList1.Images.Add("img3", Properties.Resources.img3);
imageList1.Images.Add("img4", Properties.Resources.img4);
imageList1.Images.Add("img5", Properties.Resources.img5);
for (int i = 0; i < 6; i++) {
    var item = new ListViewItem(
        "Image #" + i, // Text
        "img" + i      // <== Use key here, not index
    );
    listView1.Items.Add(item);
}

If I remove an entry with ...

listView1.Items[1].Remove();
imageList1.Images.RemoveAt(1);

... it works correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM