Add type descriptors to all List<T> for a generic implementation of property grid expansion?

1.3k views Asked by At

I defined a custom ExpandableObjectConverter for collections:

internal class ExpandableCollectionConverter : ExpandableObjectConverter
{
    public override PropertyDescriptorCollection GetProperties(
        ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        //implementation that returns a list of property descriptors,
        //one for each item in "value"
    }
}

And also have a proxy class called ExpandableObjectManager, which in essence does this:

TypeDescriptor.AddAttributes(type,
  new TypeConverterAttribute(typeof(ExpandableCollectionConverter)));

Using this method:

public static class ExpandableObjectManager
{
    public static void AddTypeDescriptor(Type tItem)
    {
        //eventually calls TypeDescriptor.AddAttributes
    }
}

Is it possible to add type descriptor in such a way that all generic List<T> will be expandable in the property grid? For example, given a simple Employee class:

class Employee
{
    public string Name { get; set; }
    public string Title { get; set; }
    public DateTime DateOfBirth { get; set; }
}

I can do this (and it works, but only for List<Employee>):

ExpandableObjectManager.AddTypeDescriptor(typeof(List<Employee>));

I would like to cover all T, not just Employee, without having to write 1 line for each possible class. I tried this - didn't work:

ExpandableObjectManager.AddTypeDescriptor(typeof(List<>));

TL;DR: Default view of a List when set as SelectedObject in the property grid:

enter image description here

Expected results:

enter image description here

Without having to add a type descriptor for List<Employee>, and instead having some generic handler for all List<T>.

1

There are 1 answers

3
Grax32 On BEST ANSWER

Edit: I added a third possibility.

I don't think any of these are wonderful solutions but here are three possibilities:

Add TypeConverterAttribute to an interface that the generic type implements. The downside here is that you may not precisely hit the types you are targetting, but it is better than option 2 because it is quite a bit more focused on the types you want.

TypeDescriptor.AddAttributes(typeof(IList), new
    TypeConverterAttribute(typeof(ExpandableCollectionConverter)));

Add the TypeConverterAttribute to the object type. The downside is that this will make your type converter the type converter for all types in your project.

TypeDescriptor.AddAttributes(typeof(object), new
    TypeConverterAttribute(typeof(ExpandableCollectionConverter)));

Create your own list type that inherits from List<> and have it register itself in the static constructor

public class CustomList<T> : List<T>
{
    static CustomList()
    {
        TypeDescriptor.AddAttributes(typeof(CustomList<T>), new TypeConverterAttribute(typeof(ExpandableCollectionConverter)));
    }
}