我有一个显示在属性网格中的类。其中一个属性是List<SomeType>
。
设置代码的最简单/最正确的方法是什么,以便我可以通过属性网格添加和删除此集合中的项目,最好使用标准CollectionEditor
。
其中一种错误的方法是:
set not being called when editing a collection
用户annakata建议我公开IEnumerable
接口而不是集合。有人可以向我提供更多细节吗?
我有一个额外的复杂功能,get
返回的集合实际上并没有指向我班级中的成员,而是来自其他成员的动态构建,如下所示:
public List<SomeType> Stuff
{
get
{
List<SomeType> stuff = new List<SomeType>();
//...populate stuff with data from an internal xml-tree
return stuff;
}
set
{
//...update some data in the internal xml-tree using value
}
}
答案 0 :(得分:6)
这是一个有点棘手的问题;解决方案涉及使用完整的.NET Framework构建(因为仅客户端框架不包含System.Design
)。您需要创建自己的CollectionEditor
子类,并告诉它在UI完成后如何处理临时集合:
public class SomeTypeEditor : CollectionEditor {
public SomeTypeEditor(Type type) : base(type) { }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
object result = base.EditValue(context, provider, value);
// assign the temporary collection from the UI to the property
((ClassContainingStuffProperty)context.Instance).Stuff = (List<SomeType>)result;
return result;
}
}
然后你必须使用EditorAttribute
:
[Editor(typeof(SomeTypeEditor), typeof(UITypeEditor))]
public List<SomeType> Stuff {
// ...
}
漫长而复杂,是的,但它确实有效。在集合编辑器弹出窗口中单击“确定”后,可以再次打开它,值将保留。
注意:您需要导入名称空间System.ComponentModel
,System.ComponentModel.Design
和System.Drawing.Design
。
答案 1 :(得分:0)
只要该类型具有公共无参数构造函数,它就可以正常工作:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
class Foo {
private readonly List<Bar> bars = new List<Bar>();
public List<Bar> Bars { get { return bars; } }
public string Caption { get; set; }
}
class Bar {
public string Name { get;set; }
public int Id { get; set; }
}
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form {
Controls = { new PropertyGrid { Dock = DockStyle.Fill,
SelectedObject = new Foo()
}}});
}
}