4

我一直在努力让自定义 PropertyDescriptors 以我想要的方式使用 PropertyGrid。

前提:

  • 我有一个名为“Animal”的类,其中包含属性AgeTypeLocationName
  • 我有另一个名为“AnimalGroup”的类,其中包含List<Animal>存储动物的位置。包含此列表的类成员称为Members
  • 在程序的 UI 中,表单元素将列出分配给 PropertGrid属性PropertyGrid的 AnimalGroup 中的动物。SelectedObject

第三个子弹我可以很容易地开始工作(见下图)。

PropertyGrid 显示 AnimalGroup 的成员。

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

不幸的是,如上图所示,属性值只是 Animal 的 ToString 方法返回的值。

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

以下是我遵循的教程:

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

动物.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;
    }
}

动物组.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;
    }
}

仅供参考,我知道代码有点荒谬(有名字的动物,动物群体等)。

4

1 回答 1

3

看起来你缺少一个转换器:

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

发现此 Code Project Customized display of collection data in a PropertyGrid很有帮助。

于 2012-08-10T14:13:05.660 回答