代码之家  ›  专栏  ›  技术社区  ›  Andreas Brinck

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

  •  2
  • Andreas Brinck  · 技术社区  · 14 年前

    我有一个类显示在属性网格中。其中一个属性是 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 回复  |  直到 14 年前
        1
  •  6
  •   Bradley Smith    14 年前

    这是一个有点棘手的问题;解决方案涉及使用完整的.NET框架进行构建(因为仅客户端的框架不包括 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 .

        2
  •  0
  •   Marc Gravell    14 年前

    只要类型具有公共的无参数构造函数 它应该就行了 :

    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()
            }}});
        }
    }