C# 将类别属性添加到PropertyDescriptor

C# 将类别属性添加到PropertyDescriptor,c#,typedescriptor,propertydescriptor,C#,Typedescriptor,Propertydescriptor,我有一组自定义PropertyDescriptor,我也想添加类别,以便它们以更有序的方式显示在PropertyGrid中。我希望每种类型的PropertyDescriptor都归入一个特定的类别 我已尝试使用TypeDescriptor.AddAttributes()向现有PropertyDescriptor添加属性,但没有添加category属性 CategoryAttribute intrinsicPropertyCategory = new CategoryAttribute("Intr

我有一组自定义PropertyDescriptor,我也想添加类别,以便它们以更有序的方式显示在PropertyGrid中。我希望每种类型的PropertyDescriptor都归入一个特定的类别

我已尝试使用TypeDescriptor.AddAttributes()向现有PropertyDescriptor添加属性,但没有添加category属性

CategoryAttribute intrinsicPropertyCategory = new CategoryAttribute("Intrinsic Properties");
currentDescriptor = new IntrinsicPropertyDescriptor(def);
TypeDescriptor.AddAttributes(currentDescriptor, new Attribute[] { intrinsicPropertyCategory });
我还尝试在我的一个PropertyDescriptor的构造函数中使用TypeDescriptor.AddAttributes(),如下所示。但它也不起作用

public IntrinsicPropertyDescriptor(IntrinsicPropertyDef propDef): base(propDef.Key, propDef.Attributes)
{
this._type = propDef.Type;
this._key = propDef.Key;
this._readOnly = propDef.ReadOnly;

CategoryAttribute intrinsicPropertyCategory = new CategoryAttribute("Intrinsic Properties");
TypeDescriptor.AddAttributes(this, new Attribute[] { intrinsicPropertyCategory });
}
我不想把时间花在我为什么要做我正在做的事情的细节上。但在上面的示例中,IntrinsicPropertyDef是一个定义属性(包括名称、显示名称和类型)的类。因此propDef.Attributes包括DisplayNameAttribute

IntrinsicPropertyDef可以使用两个不同的自定义PropertyDescriptor IntrinsicPropertyDescriptor和InferedInstrinsicPropertyDescriptor显示。每个IntrinsicPropertyDescriptor都应该有一个类别属性“内在属性”,而每个InferedinicPropertyDescriptor都应该有一个类别属性“推断内在属性”。

我相信您可以重写
类别:

public override string Category { get {return "Foo";}}
对于其他场景;通常,使用自定义的
PropertyDescriptor
,可以在构造函数中指定属性。您需要展开
属性[]
参数以包括
类别属性
。如果需要进行任何处理,可以使用静态方法-未测试:

static Attribute[] AddCategory(Attribute[] attributes, string category) {
    Array.Resize(ref attributes, attributes.Length + 1);
    attributes[attributes.Length - 1] = new CategoryAttribute(category);
    return attributes;
}
public IntrinsicPropertyDescriptor(IntrinsicPropertyDef propDef)
     : base(propDef.Key, AddCategory(propDef.Attributes, "Foo"))
{...}

另外-请注意,要使用
PropertyDescriptor
,系统必须找到它。。。处置规则为:

  • 对于
    PropertyGrid
    TypeConverter
    提供属性,默认为实例的属性(如下)
  • 例如:
    • ICustomTypeDescriptor
      已选中
    • 否则,它将检查实例或类型的已注册
      TypeDescriptionProvider
    • 否则将使用反射
  • 对于类型:
    • 它检查类型的注册
      TypeDescriptionProvider
    • 否则将使用反射
  • 有关列表:
    • IListSource
      已选中并解析为列表(处理继续)
    • ITypedList
      已选中
    • 否则,将检查列表类型是否有非对象索引器,即
      public SomeType this[int index]{get;}
      • 如果找到这样的属性,则使用类型
        SomeType
        的属性,如上所述
    • 否则,如果列表不是空的,则使用第一个实例的属性(
      list[0]
      ),如上所述
    • 否则,元数据不可用
我相信您可以覆盖
类别

public override string Category { get {return "Foo";}}
对于其他场景;通常,使用自定义的
PropertyDescriptor
,可以在构造函数中指定属性。您需要展开
属性[]
参数以包括
类别属性
。如果需要进行任何处理,可以使用静态方法-未测试:

static Attribute[] AddCategory(Attribute[] attributes, string category) {
    Array.Resize(ref attributes, attributes.Length + 1);
    attributes[attributes.Length - 1] = new CategoryAttribute(category);
    return attributes;
}
public IntrinsicPropertyDescriptor(IntrinsicPropertyDef propDef)
     : base(propDef.Key, AddCategory(propDef.Attributes, "Foo"))
{...}

另外-请注意,要使用
PropertyDescriptor
,系统必须找到它。。。处置规则为:

  • 对于
    PropertyGrid
    TypeConverter
    提供属性,默认为实例的属性(如下)
  • 例如:
    • ICustomTypeDescriptor
      已选中
    • 否则,它将检查实例或类型的已注册
      TypeDescriptionProvider
    • 否则将使用反射
  • 对于类型:
    • 它检查类型的注册
      TypeDescriptionProvider
    • 否则将使用反射
  • 有关列表:
    • IListSource
      已选中并解析为列表(处理继续)
    • ITypedList
      已选中
    • 否则,将检查列表类型是否有非对象索引器,即
      public SomeType this[int index]{get;}
      • 如果找到这样的属性,则使用类型
        SomeType
        的属性,如上所述
    • 否则,如果列表不是空的,则使用第一个实例的属性(
      list[0]
      ),如上所述
    • 否则,元数据不可用

是的,您建议的类别覆盖非常有效。我知道如何使用构造函数,但没有想到使用静态方法来简化必须作为参数传递给构造函数的代码。谢谢是的,你建议的类别覆盖效果很好。我知道如何使用构造函数,但没有想到使用静态方法来简化必须作为参数传递给构造函数的代码。谢谢