简体   繁体   English

在 Visual Studio 的 imagelist 中替换图像而不更改索引

[英]Replace image in imagelist in visual studio without changing the index

I'm using an imagelist with about 100 different icons to be used in a listview in a C# project using Winforms我正在使用带有大约 100 个不同图标的图像列表,用于使用 Winforms 的 C# 项目的列表视图

The images are referred to by the listview by their index.列表视图通过它们的索引引用图像。

Now there has been a graphical overhaul, and all of the icons need to be replaced.现在已经进行了图形大修,所有图标都需要更换。 What I did so far was open up the imagelist in the Visual Studio editor, delete image x with index 5, and then add a new version of image x.到目前为止,我所做的是在 Visual Studio 编辑器中打开图像列表,删除索引为 5 的图像 x,然后添加新版本的图像 x。

在此处输入图像描述

The problem with approach is that when deleting image x, all other images with an index higher than 5 are shifted.方法的问题在于,当删除图像 x 时,索引高于 5 的所有其他图像都会被移动。 And after adding the new version of the icon, I have to click the UP arrow about 95 times to get my new version at index 5 again.添加新版本的图标后,我必须单击向上箭头大约 95 次才能再次在索引 5 处获得我的新版本。

Does anyone know a less painful, and less error prone method to achieve the same result?有谁知道一种不那么痛苦、更不容易出错的方法来实现相同的结果?

Editing the.designer.cs file doesn't really help as it only lists the names of the icons and their index编辑 .designer.cs 文件并没有真正的帮助,因为它只列出了图标的名称及其索引

    // 
    // NavigatorImageList
    // 
    this.NavigatorImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("NavigatorImageList.ImageStream")));
    this.NavigatorImageList.TransparentColor = System.Drawing.Color.Transparent;
    this.NavigatorImageList.Images.SetKeyName(0, "dummy.png");
    this.NavigatorImageList.Images.SetKeyName(1, "Attribute.png");
    this.NavigatorImageList.Images.SetKeyName(2, "Operation.png");
    this.NavigatorImageList.Images.SetKeyName(3, "Element.png");
    this.NavigatorImageList.Images.SetKeyName(4, "Diagram.png");
    this.NavigatorImageList.Images.SetKeyName(5, "Package_element.png");
    // ...continues like this for all items ....

The actual images are stored in the.resx file, but they are in a binary format, so also not really an option to edit them there实际图像存储在 .resx 文件中,但它们是二进制格式,因此也不是在那里编辑它们的真正选项

  <data name="NavigatorImageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
    <value>
        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAB2
        1gAAAk1TRnQBSQFMAgEBYwEAAYgBAgGIAQIBEAEAARABAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAFA
        AwABkAEBAgABAQEAARAGAAHIJgABeAEtAfABHAHwARwB8AEcAfABHAHwARwWAAG4ATUBMAElATABJQEw
... and many many more lines like this...

I know referring to the images by their index might have been a mistake, but it's a bit late in the game to change that now我知道通过索引引用图像可能是一个错误,但现在改变它有点晚了

TL;DR TL;博士

I'm looking for an easy way to replace the images in my imagelist without having to change my existing working code that relies on the image indexes.我正在寻找一种简单的方法来替换图像列表中的图像,而无需更改依赖图像索引的现有工作代码。

The Image List Editor has an Image property as well which is not browsable by default. Image List Editor 也有一个 Image 属性,默认情况下它是不可浏览的。 As an option you can make that property visible and then you can easily replace the image at design time without any problem.作为一个选项,您可以使该属性可见,然后您可以在设计时轻松替换图像而不会出现任何问题。

Look at the following picture and see Image property:查看下图并查看Image属性:

在此处输入图像描述

Here is My Image Collection Editor.这是我的图像收藏编辑器。 It's basically the code of the original Image Collection editor with a small change, finding the collection editor's PropertyGrid and resetting its BrowsableAttributes property.它基本上是原始图像集合编辑器的代码,稍作改动,找到集合编辑器的PropertyGrid并重置其BrowsableAttributes属性。

public class MyImageListEditor : CollectionEditor
{
    Type ImageListImageType;
    public MyImageListEditor(Type type) : base(type)
    {
        ImageListImageType = typeof(ControlDesigner).Assembly
            .GetType("System.Windows.Forms.Design.ImageListImage");
    }
    protected override string GetDisplayText(object value)
    {
        if (value == null)
            return string.Empty;
        PropertyDescriptor property = TypeDescriptor.GetProperties(value)["Name"];
        if (property != null)
        {
            string str = (string)property.GetValue(value);
            if (str != null && str.Length > 0)
                return str;
        }
        if (value.GetType() == ImageListImageType)
            value = (object)((dynamic)value).Image;
        string name = TypeDescriptor.GetConverter(value).ConvertToString(value);
        if (name == null || name.Length == 0)
            name = value.GetType().Name;
        return name;
    }
    protected override object CreateInstance(Type type)
    {
        return ((UITypeEditor)TypeDescriptor.GetEditor(ImageListImageType,
            typeof(UITypeEditor))).EditValue(Context, null);
    }
    protected override CollectionEditor.CollectionForm CreateCollectionForm()
    {
        CollectionEditor.CollectionForm collectionForm = base.CreateCollectionForm();
        collectionForm.Text = "My Image Collection Editor";
        var overArchingTableLayoutPanel =  
            (TableLayoutPanel)collectionForm.Controls["overArchingTableLayoutPanel"];
        var propertyBrowser =  
            (PropertyGrid)overArchingTableLayoutPanel.Controls["propertyBrowser"];
        propertyBrowser.BrowsableAttributes = new AttributeCollection();

        return collectionForm;
    }
    protected override IList GetObjectsFromInstance(object instance)
    {
        return (IList)(instance as ArrayList) ?? (IList)null;
    }
}

To register this editor for image list, the easiest solution is registering it inside the constructor of the base class:要为图像列表注册此编辑器,最简单的解决方案是在基础 class 的构造函数中注册它:

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

public class MyBaseForm : Form
{
    public MyBaseForm()
    {
        TypeDescriptor.AddAttributes(typeof(ImageList.ImageCollection),
            new Attribute[] { 
                new EditorAttribute(typeof(MyImageListEditor), typeof(UITypeEditor)) });
    }
}

Then just close all designers, rebuild solution, close and reopen VS.然后只需关闭所有设计器,重建解决方案,关闭并重新打开 VS。

That's all!就这样!

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

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