简体   繁体   English

Winforms将图像插入索引处的ListView / ImageList中

[英]Winforms insert image into ListView / ImageList at index

Winforms, C#, VS2017 Winforms,C#,VS2017

ImageList does not have an Insert method (however ListViewItemCollection does). ImageList没有Insert方法(但是ListViewItemCollection有)。 I have tried a few different ways to insert a new image into the middle of a ListView and it's LargeImageList, but not getting it to work quite properly. 我尝试了几种不同的方法将新图像插入到ListView的中间,它是LargeImageList,但没有使其正常工作。

Anyone have any tried and true code that works properly? 任何人都有经过实践检验的正确代码吗?

This is what I have, but the images don't get synced properly to the items in the list. 这就是我所拥有的,但是图像无法正确同步到列表中的项目。

    protected void InsertThumbnail(string key, string keySelected)
    {
        var newImageList = new ImageList()
        {
            ImageSize = new Size(thumbWidth, thumbHeight)
        };
        var itemNew = new ListViewItem();
        var foundSelected = false;

        //lvAllPages.BeginUpdate();

        for (int i = 0; i < lvAllPages.Items.Count; i++)
        {
            var item = lvAllPages.Items[i];
            newImageList.Images.Add(item.Tag.ToString(), lvAllPages.LargeImageList.Images[i]);

            if (item.Tag.ToString() == keySelected)
            {
                var image = batch.GetThumbnail(key);
                newImageList.Images.Add(key, image);
                itemNew = new ListViewItem()
                {
                    BackColor = Color.Aquamarine,
                    ImageIndex = i,
                    Tag = key,
                };

                if (isLocal)
                    itemNew.Text = $"{GetFileName(key)} (insert) - {itemNew.ImageIndex}";

                foundSelected = true;
            }

            if (foundSelected)
            {
                item.ImageIndex = item.ImageIndex + 1;
                if (isLocal)
                    item.Text = $"{GetFileName(item.Tag.ToString())} - {item.ImageIndex}";
            }
        }

        lvAllPages.LargeImageList.Dispose();
        lvAllPages.LargeImageList = newImageList;
        lvAllPages.Items.Insert(itemNew.ImageIndex, itemNew);
    }

One more related thing, but not pertinent to the problems I am having. 还有另一件事,但与我遇到的问题无关。 For anyone looking at this question and having similar issues, this helped with the issue of sorting items after inserting a new one. 对于任何关注此问题并有类似问题的人,这有助于解决在插入新项目后对项目进行排序的问题。 Default behavior when you insert a new ListViewItem at a given index, it will appear at the bottom of the list. 当您在给定的索引处插入新的ListViewItem时的默认行为,它将出现在列表的底部。 I found this handy class to keep items sorted by index, which solved that problem: 我发现这个方便的类可以使项目按索引排序,从而解决了该问题:

class CompareByIndex : IComparer { private readonly ListView _listView; class CompareByIndex:IComparer {私有只读ListView _listView;

public CompareByIndex(ListView listView)
{
    this._listView = listView;
}
public int Compare(object x, object y)
{
    int i = this._listView.Items.IndexOf((ListViewItem)x);
    int j = this._listView.Items.IndexOf((ListViewItem)y);
    return i - j;
}

} }

And in the form load: 并在形式加载中:

lvAllPages.ListViewItemSorter = new CompareByIndex(lvAllPages); lvAllPages.ListViewItemSorter =新的CompareByIndex(lvAllPages);

Obviously, that's a design decision. 显然,这是设计决定。 ImageList.Images is a ImageCollection and as such, it implements the IList interface. ImageList.Images是一个ImageCollection ,因此,它实现了IList接口。

Unfortunately, the Insert() method is allowed to throw a NotSupportedException . 不幸的是,允许Insert()方法抛出NotSupportedException And that's what the list will do when used like a IList : 这就是像IList一样使用时列表将要做的事情:

((IList)imageList.Images).Insert(5, new Bitmap(10,10));

System.NotSupportedException: 'Specified method is not supported.' System.NotSupportedException:'不支持指定的方法。

In order to have the images shown in a specific order, use the Add() method which takes the key: 为了使图像以特定顺序显示,请使用采用以下键的Add()方法:

imageList.Images.Add("1", new Bitmap(100,100));

That should also enable you to replace the image: 那也应该使您能够替换图像:

imageList.Images.RemoveByKey("1");
imageList.Images.Add("1", new Bitmap(200,200));

For that to work, you need to set the Sorting property: 为此,您需要设置Sorting属性:

listView1.Sorting = SortOrder.Ascending;

For storing additional information like path etc. use anotther data structure with the same key. 为了存储路径等其他信息,请使用具有相同密钥的其他数据结构。


Here's the code: 这是代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    ImageList imageList = new ImageList();
    Dictionary<string, Metadata> metadata = new Dictionary<string, Metadata>();
    private string dir = @"H:\temp";

    private void button1_Click(object sender, EventArgs e)
    {
        // You would set this in the designer, probably
        listView1.Sorting = SortOrder.Ascending;
        listView1.View = View.LargeIcon;
        listView1.LargeImageList = imageList;

        // Make sure we start from the beginning
        listView1.Items.Clear();
        imageList.Images.Clear();
        metadata.Clear();

        // Add items
        for (int i = 0; i < 10; i++)
        {
            var filename = "1 ("+(i+1)+").png"; // Just strange names I have
            var fullFileName = Path.Combine(dir, filename);
            imageList.Images.Add(i.ToString(), Bitmap.FromFile(fullFileName));
            metadata.Add(i.ToString(), new Metadata{Path = fullFileName});

            listView1.Items.Add(i.ToString(), "Image " + i, i.ToString());
        }

        // Update view
        listView1.Refresh();
        listView1.Invalidate();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        for (int i = 3; i < 6; i++)
        {
            var filename = "1 ("+(i+2)+").png";
            var fullFileName = Path.Combine(dir, filename);
            // Change image
            imageList.Images.RemoveByKey(i.ToString());
            imageList.Images.Add(i.ToString(), Bitmap.FromFile(fullFileName));
            // Match metadata and image
            metadata[i.ToString()] = new Metadata{Path = fullFileName};
        }
        listView1.Refresh();
    }

    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (listView1.SelectedItems.Count > 0)
        {
            var key = listView1.SelectedItems[0].ImageKey;

            label1.Text = metadata[key].Path;
        }
        else
        {
            label1.Text = "No image selected";
        }
    }
}

internal class Metadata
{
    internal string Path;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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