C# 在不更改索引的情况下替换visual studio中imagelist中的图像
我正在使用一个带有大约100个不同图标的imagelist,在一个使用Winforms的C#项目的listview中使用 这些图像由listview通过其索引引用 现在有了一个图形化的大修,所有的图标都需要更换。 到目前为止,我所做的是在VisualStudio编辑器中打开imagelist,删除索引为5的图像x,然后添加新版本的图像x 该方法的问题在于,删除图像x时,索引大于5的所有其他图像都会移位。 在添加图标的新版本后,我必须单击向上箭头大约95次才能再次在索引5处获得我的新版本 有人知道一种不那么痛苦、不那么容易出错的方法来达到同样的效果吗 编辑.designer.cs文件并没有真正的帮助,因为它只列出图标的名称及其索引C# 在不更改索引的情况下替换visual studio中imagelist中的图像,c#,.net,visual-studio,winforms,windows-forms-designer,C#,.net,Visual Studio,Winforms,Windows Forms Designer,我正在使用一个带有大约100个不同图标的imagelist,在一个使用Winforms的C#项目的listview中使用 这些图像由listview通过其索引引用 现在有了一个图形化的大修,所有的图标都需要更换。 到目前为止,我所做的是在VisualStudio编辑器中打开imagelist,删除索引为5的图像x,然后添加新版本的图像x 该方法的问题在于,删除图像x时,索引大于5的所有其他图像都会移位。 在添加图标的新版本后,我必须单击向上箭头大约95次才能再次在索引5处获得我的新版本 有人知
//
// 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 ....
实际图像存储在.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...
aaaaad/////aqaaaaaagaaaafdtexn0zw0uv2luzg93cy5gb3jtcywgvmvyc2lvbj00ljaumc4w
LCBDDWX0DXJLPW5LDXRYYWWIFB1YMXPY0TLEVA2VUPWI3N2E1YZU2MTKZNGUWODKFAQAAACZTEXN0
ZW0UV2LUZG93CY5GB3JTCY5JBWFNZUXPC3RTDHJLYW1CGEAAAERGF0YQCCAGAAAKDAADWMAAB2
1GAAAK1TRNQBSQFGMAGEBYWEAGBAGGIAQIBEAARABAAT/AREBAJ/AUIBTQE2BWANGMAASGDAAFA
Awabkaebagabaqaearagahijgabeaetafabhahwarwb8aecafabhahwarwwaag4atubmaelatabjqew
... 还有更多像这样的台词。。。
我知道根据他们的索引引用图片可能是一个错误,但现在改变这一点已经有点晚了
TL;博士
我正在寻找一种简单的方法来替换imagelist中的图像,而不必更改依赖于图像索引的现有工作代码。图像列表编辑器也有一个默认不可浏览的图像属性。作为一个选项,您可以使该属性可见,然后可以在设计时轻松替换图像,而不会出现任何问题 查看下图并查看
图像
属性:
这是我的图像收集编辑器。它基本上是原始图像采集编辑器的代码,只需稍作更改,即可找到采集编辑器的PropertyGrid
并重置其属性
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;
}
}
要为图像列表注册此编辑器,最简单的解决方案是在基类的构造函数中注册它:
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)) });
}
}
然后关闭所有设计器,重建解决方案,关闭并重新打开VS
就这些 如果这是一个.NET项目,其中ImageList位于
*.resx
文件中,为什么不直接手工编辑*.resx
文件呢?或者,如果是WinForms项目,请手动编辑*designer.cs
文件。感谢您的输入。我已经在问题中添加了一些关于这些的细节。如果我处在您的位置,我会使用XmlDocument
编写一个Linqpad程序,对resx文件进行大量更改(Linqpad是免费的,但您需要为有用的功能付费)。也就是说,我认为你可以让一个resx文件使用链接文件,而不是将它们直接存储在resx文件中,作为XML中的Base64。我只能选择一个图像文件,然后像这样将其添加到resx文件中。您不必在设计器中添加这些图像。制作一个字典
,使用索引对->资源名,将所有图像作为资源添加到仅资源库(仅包含资源的dll和按名称或索引或索引范围返回位图的公共方法),并在运行时填充图像列表。如果您更改了资源库中的某些内容,您可能不必更改填充ImageList的方法中的任何内容,只要您使用索引来定义对象的图像源。哇,这看起来很有希望,很酷!我会尝试一下,然后回来报告……不用担心。应用该解决方案非常容易。花足够的时间来测试它;然而,我已经测试过了,并且工作得很好。如果您发现任何问题,请告诉我。我应用MyImageListEditor的方法不是唯一的方法,而是最简单的方法。它依赖于一个事实:Windows窗体设计器在设计窗体的基本窗体的构造函数中运行代码。这就是为什么我添加了一个虚拟的基本表单,并将注册码放在那里。要了解有关designer如何工作的更多信息,您可以查看一下。注册编辑器的另一个选项(您不需要使用)是在VS包中进行注册,例如更改ColorEditor
以显示一些自定义颜色。谢谢,这非常有效!正是我要找的!