Making a PropertyGrid´s property expandable, in one second

The PropertyGrid control is one of the most useful controls in the .Net framework. As you probably know, it uses reflection to guess all the public properties of an object, showing them in a user-friendly interface where you can see and change property values.




The wonderful thing about this control is that it automatically creates the user interface and behaves correctly for ReadOnly properties, multiple object selections, anykind of datatype, specific user interfaces for data types (like combos, ColorPickers, DateTimePicker), etc... The list of features is almost endless.

Someone asked me today how to take advantage of another of it´s features: Expandable Properties.

If you don´t know exactly what I´m talking about, let me introduce it with the following example:

public class Car

{

...

private int mLength;

public int Length

{

get{return mLength;}

set{mLength = value;}

}


private Environment mEnv;

public Environment Env

{

get{return mEnv;}

set{mEnv = value;}

}

...

}


And now, somewhere else you use that class, putting it into a PropertyGrid, so you can inspect and change it´s contents:


Car mCar = new Car();

this.propertyGrid1.SelectedObject = mCar;


The property grid will behave correctly for the "Length" property, allowing you to change it´s value and detecting if the value entered is an "int". BUT, what happens with the "Env" property? It is not a basic DataType. It´s not a default complex type of the FrameWork.

By default, the PropertyGrid will only show the string description of the object Env (the return value of the ToSring() method, which can be overriden), making it read only. If only we could make the PropertyGrid treat that object as an expandable property, allowing us to see it´s internals...

Easy as shit! Add this to the definition of the property:


[TypeConverter(typeof(ExpandableObjectConverter))]

public Environment Env
{
get{return mEnv;}
set{mEnv = value;}
}


This way, you tell the PropertyGrid it should treat that object that way, and it will add at it´s left a Plus/Minus sign allowing you to expand the object. Easy, isn´t it?

Note: You have to include a "#using System.ComponentModel" to make this work.