我的目标是创建一个显示一些图像的自定义控件,可以由该控件的用户添加/交换。因此,如果将其添加到表单中,GUI设计者应该能够更改控件提供的部分或全部图像,以编辑相应的属性。
在我的测试项目中,我有一个带有4个属性的简单控件:
public Image MyImage { get; set; } = null;
public List<int> MyListOfInt { get; set; } = new List<int>();
public List<Image> MyListOfImages { get; set; } = new List<Image>();
public ImageList MyImageList { get; set; } = new ImageList();
在Windows窗体项目中使用此控件,单击
MyImage
显示“选择资源”对话框。确定
MyListOfInt
打开“Int32集合编辑器”对话框。确定
MyListOfImages
显示“图像集编辑器”对话框,但使用“添加”按钮会显示消息:
'无法创建
System.Drawing.Image
的实例,因为它是一个。{ 抽象类。'
MyImageList
显示了一个无法编辑的emtpy列表。
我的问题是,如果有可能告诉VS Designer在点击“添加”按钮时使用“选择资源”对话框以及需要做什么?
答案 0 :(得分:1)
从Marwie的评论开始,我能够解决问题。
为了使用CollectionEditor成功保存,集合应满足三个要求:
IList
接口(继承自System.Collections.CollectionBase
在大多数情况下是最佳选择)。Add
和/或AddRange
所以我创建了一个包含
的类'ImageItem'图片
[Category("ImageItem")]
[DefaultValue(typeof(Image), null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Image Picture {
get { return m_Picture; }
set { m_Picture = value; }
}
名称(可选)
[Category("ImageItem")]
[DefaultValue(typeof(string), "")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string Name {
get { return m_Name; }
set { m_Name = value; }
}
一个值(可选)
[Category("ImageItem")]
[DefaultValue(typeof(int), "-1")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Value {
get { return m_Value; }
set { m_Value = value; }
}
和一个集合'ImageCollection'根据上述条件保存此类的实例:
public class ImageCollection : CollectionBase
public ImageItem this[int i]
public ImageItem Add(ImageItem item)
然后我创建了一个仅包含此集合的控件,用一个图像初始化:
public partial class MyControl: UserControl
{
public MyControl() {
InitializeComponent();
}
private ImageCollection m_MyImageCollection = new ImageCollection()
{ new ImageItem(0, "Failure", Properties.Resources.Cross), new ImageItem(1, "OK", Properties.Resources.Tickmark) };
[Browsable(true), Category("A Test"), DisplayName("Image Collection (ImageCollection)"), Description("Edit image collection")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
public ImageCollection MyImageCollection {
get { return m_MyImageCollection; }
}
}
编译此代码后,设计人员会显示该属性。现在可以使用常见的设计器GUI控件添加图像。
在我的表单上使用它时,我尝试更改编译到此控件中的默认图像,但我认识到,设计人员无法删除内容。它只存储“添加”操作。所以我修改了代码,在集合中搜索具有相同ID的另一个项目。如果有一个可用,则删除该实例并替换为新实例。因此,我也必须实施AddRange
方法。
public ImageItem Add(ImageItem item) {
for(int i = 0; i < InnerList.Count; i++) {
if(InnerList[i] is ImageItem) {
if(((ImageItem)InnerList[i]).Value == item.Value) {
InnerList.RemoveAt(i);
}
}
}
this.InnerList.Add(item);
return item;
}
public void AddRange(ImageItem[] array) {
foreach(ImageItem item in array) {
Add(item);
}
}
所以我的最后课程是:
public class ImageItem {
private int m_Value = -1;
private string m_Name = "ImageItem";
private Image m_Picture = null;
[Category("ImageItem")]
[DefaultValue(typeof(int), "-1")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Value {
get { return m_Value; }
set { m_Value = value; }
}
[Category("ImageItem")]
[DefaultValue(typeof(string), "")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string Name {
get { return m_Name; }
set { m_Name = value; }
}
[Category("ImageItem")]
[DefaultValue(typeof(Image), null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Image Picture {
get { return m_Picture; }
set { m_Picture = value; }
}
public ImageItem() { }
public ImageItem(int value, string name, Image image) {
this.m_Value = value;
this.m_Name = name;
this.m_Picture = image;
}
}
ImageCollection
:
public class ImageCollection : CollectionBase {
public ImageCollection() {}
public ImageItem this[int i]
{
get { return (ImageItem)this.InnerList[i]; }
set { this.InnerList[i] = value; }
}
public ImageItem Add(ImageItem item) {
for(int i = 0; i < InnerList.Count; i++) {
if(InnerList[i] is ImageItem) {
if(((ImageItem)InnerList[i]).Value == item.Value) {
InnerList.RemoveAt(i);
}
}
}
this.InnerList.Add(item);
return item;
}
public void AddRange(ImageItem[] array) {
foreach(ImageItem item in array) {
Add(item);
}
}
public void Remove(ImageItem item) {
this.InnerList.Remove(item);
}
public bool Contains(ImageItem item) {
return this.InnerList.Contains(item);
}
public ImageItem[] GetValues() {
ImageItem[] item= new ImageItem[this.InnerList.Count];
this.InnerList.CopyTo(0, item, 0, this.InnerList.Count);
return item;
}
protected override void OnInsert(int index, object value) {
base.OnInsert(index, value);
}
}
答案 1 :(得分:1)
我从MSDN得到了另一个答案: How to edit UserControl attribute of type ImageList in Designer PropertyGrid (add/remove/exchange images)
我将简要介绍这个想法。首先使用ImageList
属性创建一个新控件。
public partial class NewControl : UserControl {
public NewControl() {
InitializeComponent();
}
public ImageList MyImageList { get; set; } = null;
}