ITypedList and PropertyDescriptor simplified

Most of the time during databinding, you need some columns which are not present in your datasource object or collection object. At that time with the help of PropertyDescriptor and ITypedList interface, any number of virtual properties can be created and same can be added as columns.

e.g.

class A
{
public int x { get; set; }
public string name { get; set; }
}

class B
{
public List<A> aObj { get; set; }
public string empName { get; set; }
}

So if we should have some collection of type class B but with columns as empName, name, x and other based on combination of any of these, ITypedList can be very useful.

Here is the ITypedList and PropertyDescriptor modified for the above structure defined.

public class CollectionB : List<B>, ITypedList
{
      private PropertyDescriptorCollection propertyDescriptors;

public void CalculatePropertyDescriptors()
{
// start out with the properties that are really in the MasterRecord
PropertyDescriptorCollection origProperties = TypeDescriptor.GetProperties(typeof(B));

ArrayList properties = new ArrayList();

//this will Add all proprties of B apart from of type A
foreach (PropertyDescriptor desc in origProperties)
       if (!typeof(A).IsAssignableFrom(desc.PropertyType))
properties.Add(desc);

foreach (var item in this[0].aObj)
{
properties.Add(new PropertySummaryDescriptor(item.name.ToString()));
}

// Last, convert the ArrayList back into a PropertyDescriptorCollection.
propertyDescriptors = new PropertyDescriptorCollection((PropertyDescriptor[])properties.ToArray(typeof(PropertyDescriptor)));
}

#region ITypedList Members

public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
return propertyDescriptors;
}

public string GetListName(PropertyDescriptor[] listAccessors)
{
      return "";//Can be left blank
}

#endregion

}

Here is the Property Descriptor :

public class PropertySummaryDescriptor : PropertyDescriptor
{

public PropertySummaryDescriptor(string name)
: base(name, null)
{
}

public override bool CanResetValue(object component)
{
return false;
}

public override Type ComponentType
{
get { return typeof(B); }
}

public override object GetValue(object component)
{

B pr = (B)component;
    int x = 0;

    foreach (A a in pr.aObj)
if (a.name == this.Name)
x = a.x;
return x;

}

public override bool IsReadOnly
{
get { return true; }
}

public override Type PropertyType
{
get { return typeof(int); }
}

public override void ResetValue(object component)
{

}

public override void SetValue(object component, object value)
{

}

public override bool ShouldSerializeValue(object component)
{
return true;
}
}