I have a set of custom PropertyDescriptor that I want to add categories too so they display in a more organized fashion in a PropertyGrid. I want each type of PropertyDescriptor to go into a specific Category.
I've tried using TypeDescriptor.AddAttributes() to add attributes to an existing PropertyDescriptor, but the category attribute is not added.
CategoryAttribute intrinsicPropertyCategory = new CategoryAttribute("Intrinsic Properties");
currentDescriptor = new IntrinsicPropertyDescriptor(def);
TypeDescriptor.AddAttributes(currentDescriptor, new Attribute[] { intrinsicPropertyCategory });
I've also tried using TypeDescriptor.AddAttributes() in the constructor for one of my PropertyDescriptors as shown below. But it doesn't work either.
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 });
}
I'd rather not spend the time going in to detail of why I'm doing what I'm doing. But in the example above IntrinsicPropertyDef is a class that defines a property including a Name, Display Name and Type. So propDef.Attributes includes the DisplayNameAttribute.
An IntrinsicPropertyDef can be displayed with two different custom PropertyDescriptors IntrinsicPropertyDescriptor, and InferedIntrinsicPropertyDescriptor. Every IntrinsicPropertyDescriptor should have a category attribute "Intrinsic Properties", and every InferedIntrinsicPropertyDescriptor should have a category attribute "Inferred Intrinsic Properties".
-
I believe you can just override the
Category
:public override string Category { get {return "Foo";}}
For other scenarios; in general with a custom
PropertyDescriptor
, you specify attributes in the constructor. You'll need to expand theAttribute[]
argument to include theCategoryAttribute
. If you need to do any processing, you can use a static method - untested: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")) {...}
Also - note that for a
PropertyDescriptor
to be used, the system must find it... the resolution rules are:- for
PropertyGrid
, theTypeConverter
provides the properties, defaulting to the properties for an instance (below) - for an instance:
ICustomTypeDescriptor
is checked- otherwise it checks for a registered
TypeDescriptionProvider
for the instance or type - otherwise reflection is used
- for a type:
- it checks for a registered
TypeDescriptionProvider
for the type - otherwise reflection is used
- it checks for a registered
- for lists:
IListSource
is checked and resolved to a list (processing continues)ITypedList
is checked- otherwise, the list type is checked for a non-object indexer - i.e.
public SomeType this[int index] {get;}
- if such is found, then the properties for the type
SomeType
are used, as defined above
- if such is found, then the properties for the type
- otherwise, if the list is not empty, the properties of the first instance (
list[0]
) are used, as defined above - otherwise, metadata is not available
Eric Anastas : Yep the Category override you suggested worked perfectly. I knew about using the constructor, but didn't think to use a static method to simplify the code I would have to pass as an argument to the constructor. Thanks! - for
0 comments:
Post a Comment