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

发布于 2024-10-02 01:04:35 字数 780 浏览 4 评论 0原文

我有一个显示在属性网格中的类。其中一个属性是 List

设置代码的最简单/正确的方法是什么,以便我可以通过属性网格添加和删除此集合中的项目,最好使用标准 CollectionEditor

错误的方法之一是这样的:

设置在编辑时不被调用集合

用户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
    }
}

I have a class which is displayed in a property grid. One of the properties is a List<SomeType>.

What's the easiest/correct way to set up the code so that I can add and remove items from this collection through the property grid, preferably using the standard CollectionEditor.

One of the wrong ways is like this:

set not being called when editing a collection

User annakata suggest that I expose an IEnumerable interface instead of a collection. Can someone please provide me with more details?

I have the extra complication that the collection returned by get doesn't actually point to a member in my class, but is build on the fly from an other member, something like this:

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
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

想你只要分分秒秒 2024-10-09 01:04:35

这是一个有点棘手的问题;该解决方案涉及使用完整的 .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

This is a slightly tricky one; the solution involves building with the full .NET Framework (since the client-only framework doesn't include System.Design). You need to create your own subclass of CollectionEditor and tell it what to do with the temporary collection after the UI is finished with it:

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

Then you have to decorate your property with the EditorAttribute:

[Editor(typeof(SomeTypeEditor), typeof(UITypeEditor))]
public List<SomeType> Stuff {
    // ...
}

Long and convoluted, yes, but it works. After you click "OK" on the collection editor popup, you can open it again and the values will remain.

Note: You need to import the namespaces System.ComponentModel, System.ComponentModel.Design and System.Drawing.Design.

椵侞 2024-10-09 01:04:35

只要该类型有一个公共无参数构造函数它就应该可以工作

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

As long as the type has a public parameterless constructor it should just work:

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()
        }}});
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文