A few days ago, Ayende mentioned a problem he ran into while using BindingList and databinding against a grid when the list contained a mixture of objects from classes in a class hierarchy, and proposed a solution involving the use of a custom TypeDescriptionProvider class.


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 that's close to some code I've been using lately:


public class TypedBindingList : BindingList, ITypedList


{


   #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.


Tomas Restrepo

Software developer located in Colombia.