A few days ago, Ayende mentioned a problem he ran into while using BindingList
I suggested that perhaps implementing ITypedList on his collection might be a solution to his problem, while being somewhat more ellegant than a custom TypeDescriptionProvider. Here's a simple implementation of ITypedList on top of BindingList
public class TypedBindingList
{
#region ITypedList Implementation
//
// ITypedList Implementation
//
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
if ( listAccessors == null || listAccessors.Length <= 0 )
{
// return the properties of items on
// this list
return GetTypeProperties(typeof(T));
} else
{
// return the properties of the specified member
// this is needed when the list is used in master/detail
// structures to ensure the child grid can figure out
// the types contained herein.
string memberName = listAccessors[0].Name;
PropertyInfo pinfo = typeof(T).GetProperty(memberName);
if ( pinfo != null )
{
Type type = pinfo.PropertyType;
if ( typeof(IList).IsAssignableFrom(type) && type.IsGenericType )
{
// if it is a generic list, find the first generic type and
// assume that's the type of the list contents
// a hack, but it could be worse :)
Type paramType = type.GetGenericArguments()[0];
return GetTypeProperties(paramType);
}
return GetTypeProperties(type);
}
return null;
}
}
public string GetListName(PropertyDescriptor[] listAccessors)
{
return string.Format("List of {0}", typeof(T).Name);
}
#endregion // ITypedList Implementation
private PropertyDescriptorCollection GetTypeProperties(Type type)
{
TypeDescriptionProvider provider = TypeDescriptor.GetProvider(type);
return provider.GetTypeDescriptor(type).GetProperties();
}
} // class TypedBindingList
It's not pretty, but it does the trick without too much hassle. In particular, it has been very useful in binding empty collections to a third-party grid control so that it still allows you to add new records (the ITypedList implementation provides the information it needs to ensure it can handle the new record returned by IBindingList.AddNew()). Of course, you can get much fancier when implementing this stuff. Frans Bouma has some pretty good articles on these kind of topics including this one.