在属性网格中编辑集合的正确方法是什么

时间:2010-11-10 14:09:12

标签: c# propertygrid

我有一个显示在属性网格中的类。其中一个属性是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
    }
}

2 个答案:

答案 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.ComponentModelSystem.ComponentModel.DesignSystem.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()
        }}});
    }
}