带有自定义 PropertyDescriptor 的 PropertyGrid [英] PropertyGrid with Custom PropertyDescriptor

查看:26
本文介绍了带有自定义 PropertyDescriptor 的 PropertyGrid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力让自定义 PropertyDescriptor 以我想要的方式与 PropertyGrid 一起工作.

I've been struggling quite a bit to get custom PropertyDescriptors to work the way I want with a PropertyGrid.

前提:

  • 我有一个名为Animal"的类,它包含属性AgeTypeLocationName>.
  • 我有另一个名为AnimalGroup"的类,其中包含存储动物的 List.包含此列表的类成员称为 Members.
  • 在程序的 UI 中,PropertyGrid 表单元素将列出分配给 PropertGrid 的 SelectedObject 属性的 AnimalGroup 中的动物.
  • I have a class called "Animal" which contains the properties Age, Type, Location, and Name.
  • I have another class called "AnimalGroup" which contains a List<Animal> where animals are stored. The class member that contains this list is called Members.
  • In the UI of the program, a PropertyGrid form element will list off the Animals in the AnimalGroup that is assigned to the PropertGrid's SelectedObject property.

第三点我可以很容易地工作(见下图).

The third bullet I can get working quite easily (see image below).

AnimalGroup 类实现了 ICustomTypeDescriptor 接口,以在其 Members 类成员中实现 Animals 的列表功能.

The AnimalGroup class implements the ICustomTypeDescriptor interface to achieve the listing functionality of the Animals in its Members class member.

不幸的是,正如您在上图中所见,属性值只是从 Animal 的 ToString 方法返回的值.

Unfortunately, as you can see in the image above, the property value is simply the value returned from the Animal's ToString method.

我希望用户能够编辑 PropertyGrid 中每个 Animal 的成员(年龄、类型、位置和名称).我怎样才能做到这一点?我认为需要某种类型的自定义编辑器.然而,老实说,我不知道从哪里开始,因为谷歌搜索并没有出现太多.

I'd like to allow users the ability to edit the members of each Animal in the PropertyGrid (Age, Type, Location, and Name). How can I achieve this? I assume there will need to be a custom editor of some type. Honestly, however, I have no idea where to get started as Googling hasn't turned up much for this.

以下是我遵循的教程:

  • Add (Remove) Items to (from) PropertyGrid at Runtime
  • Using PropertyGrid with a dictionary object (this tutorial seems really old)

如果您需要,这是我的代码(使用 .NET 4.0):

And if you need it, here's my code (using .NET 4.0):

Animal.cs

public class Animal
{
    private String _Name;

    public String Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

    private String _Type;

    public String Type
    {
        get { return _Type; }
        set { _Type = value; }
    }
    private String _Age;

    public String Age
    {
        get { return _Age; }
        set { _Age = value; }
    }
    private String _Location;

    public String Location
    {
        get { return _Location; }
        set { _Location = value; }
    }

    public override string ToString()
    {
        return this.Name + " - " + this.Type;
    }
}

AnimalGroup.cs

public class AnimalGroup : ICustomTypeDescriptor
{
    public List<Animal> Members;

    public AnimalGroup()
    {
        this.Members = new List<Animal>();
    }

    public AttributeCollection GetAttributes()
    {
        return TypeDescriptor.GetAttributes(this, true);
    }

    public string GetClassName()
    {
        return TypeDescriptor.GetClassName(this, true);
    }

    public string GetComponentName()
    {
        return TypeDescriptor.GetComponentName(this, true);
    }

    public TypeConverter GetConverter()
    {
        return TypeDescriptor.GetConverter(this, true);
    }

    public EventDescriptor GetDefaultEvent()
    {
        return TypeDescriptor.GetDefaultEvent(this, true);
    }

    public PropertyDescriptor GetDefaultProperty()
    {
        return null;
    }

    public object GetEditor(Type editorBaseType)
    {
        return TypeDescriptor.GetEditor(this, editorBaseType, true);
    }

    public EventDescriptorCollection GetEvents(Attribute[] attributes)
    {
        return TypeDescriptor.GetEvents(this, attributes, true);
    }

    public EventDescriptorCollection GetEvents()
    {
        return TypeDescriptor.GetEvents(this, true);
    }

    public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        PropertyDescriptor[] pds = new PropertyDescriptor[this.Members.Count];

        int i = 0;
        foreach (Animal a in this.Members)
        {
            pds[i] = new AnimalPropertyDescriptor(a, attributes);

            i++;
        }


        return new PropertyDescriptorCollection(pds);
    }

    public PropertyDescriptorCollection GetProperties()
    {
        return this.GetProperties(new Attribute[0]);
    }

    public object GetPropertyOwner(PropertyDescriptor pd)
    {
        return this.Members;
    }
}

AnimalPropertyDescriptor.cs

public class AnimalPropertyDescriptor : PropertyDescriptor
{
    private Animal property;

    public AnimalPropertyDescriptor(Animal target, Attribute[] attrs)
        : base(target.Name, attrs)
    {
        this.property = target;
    }

    public override bool CanResetValue(object component)
    {
        return false;
    }

    public override Type ComponentType
    {
        get { return null; }
    }

    public override object GetValue(object component)
    {
        return property;
    }

    public override bool IsReadOnly
    {
        get { return false;  }
    }

    public override Type PropertyType
    {
        get { return this.property.GetType(); }
    }

    public override void ResetValue(object component)
    {
        // Not relevant.
    }

    public override void SetValue(object component, object value)
    {
        this.property = (Animal)value;
    }

    public override bool ShouldSerializeValue(object component)
    {
        return false;
    }
}

仅供参考,我知道代码有点荒谬(带有名称的动物、动物群体等).

FYI, I am aware that the code is a bit ridiculous (Animals with names, animal groups, etc).

推荐答案

您似乎缺少转换器:

internal class AnimalConverter : ExpandableObjectConverter {

  public override object ConvertTo(ITypeDescriptorContext context, 
                                   CultureInfo culture, 
                                   object value,
                                   Type destinationType) {

    if (destinationType == typeof(string) && value is Animal) {
      Animal a = (Animal)value;
      return a.ToString();
    }
    return base.ConvertTo(context, culture, value, destinationType);
  }
}

然后装饰你的动物:

[TypeConverter(typeof(AnimalConverter))]
public class Animal {...}

发现这个代码项目 自定义显示PropertyGrid 中的集合数据很有帮助.

Found this Code Project Customized display of collection data in a PropertyGrid helpful.

这篇关于带有自定义 PropertyDescriptor 的 PropertyGrid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆