tags:

views:

246

answers:

2

Using an ORM approach in applications can often lead to the scenario where you have a collection of objects you've retrieved and would like to display them in a tabular view using a DataGridView.

In my (limited) experience, binding collections of objects using a custom BindingList to a DataGridView results in poor performance and unsatisfactory sorting. I'm looking for a generic solution to this problem such that it's straightforward to populate a DataGridView and also extract the underlying objects later.

I will describe a good solution I've found, but I'm looking for alternatives.

+1  A: 

Javier Lozano proposes converting a collection of objects to a DataTable and then convert the DataRows back to objects as necessary. His solution uses reflection to make it generic. He's even posted the code on his blog. I made some minor modifications to support Nullable types in the object, and this seems to be working well for me so far.

Cory Engebretson
+1  A: 

I am going to preface this answer with the statement that my experience is within the 2.0 Framework domain. The newer Frameworks may offer other solutions.

Below is a BindingList derived class that supports bi-directional sorting and other useful features of List. I can't take credit for the PropertyComparer sorting. I found this in an article a while back, but now I see it is all over the Internet so I unfortunately cannot cite the original source.

Another alternative is the BindingListView: http://blw.sourceforge.net. This class allows you to create a view of a List collection, like you would with a DataTable object, including the ability to define a Filter and a Sort.

public class UsefulBindingList<T> : BindingList<T>
{
    private bool _isSorted = false;
    private ListSortDirection _sortDirection;
    private PropertyDescriptor _sortProperty;

    protected override bool SupportsSortingCore
    {
     get { return true; }
    }

    protected override bool IsSortedCore
    {
     get { return _isSorted; }
    }

    protected override ListSortDirection SortDirectionCore
    {
     get { return _sortDirection; }
    }

    protected override PropertyDescriptor SortPropertyCore
    {
     get { return _sortProperty; }
    }


    public void AddRange(IEnumerable<T> collection)
    {
     IEnumerator<T> e = collection.GetEnumerator();
     while (e.MoveNext())
     {
      this.Add(e.Current);
     }
    }

    public T Find(Predicate<T> match)
    {
     List<T> items = this.Items as List<T>;
     if (items != null)
      return items.Find(match);
     else
      return default(T);
    }

    public int FindIndex(Predicate<T> match)
    {
     List<T> items = this.Items as List<T>;
     if (items != null)
      return items.FindIndex(match);
     else
      return -1;
    }

    public bool Exists(Predicate<T> match)
    {
     List<T> items = this.Items as List<T>;
     return items.Exists(match);
    }

    public void Sort()
    {
     List<T> items = this.Items as List<T>;
     if (items != null)
      items.Sort();
    }

    public void Sort(Comparison<T> comparison)
    {
     List<T> items = this.Items as List<T>;
     if (items != null)
      items.Sort(comparison);
    }

    public void Sort(IComparer<T> comparer)
    {
     List<T> items = this.Items as List<T>;
     if (items != null)
      items.Sort(comparer);
    }

    protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
    {
     _sortProperty = prop;
     _sortDirection = direction;

     List<T> items = this.Items as List<T>;
     if (items != null)
     {
      PropertyComparer<T> pc = new PropertyComparer<T>(prop, direction);
      items.Sort(pc);
      _isSorted = true;
     }
     else
     {
      _isSorted = false;
     }
     this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    protected override void RemoveSortCore()
    {
     _isSorted = false;
    }

}

public class PropertyComparer<T> : IComparer<T>
{
    private ListSortDirection _sortDirection;
    private PropertyDescriptor _property;

    public PropertyComparer(PropertyDescriptor property, ListSortDirection direction)
    {
     _property = property;
     _sortDirection = direction;
    }

    public int Compare(T x, T y)
    {
     int rv = 0;
     object vx = _property.GetValue(x);
     object vy = _property.GetValue(y);
     rv = System.Collections.Comparer.Default.Compare(vx, vy);
     if (_sortDirection == ListSortDirection.Descending)
      rv = -rv;
     return rv;
    }

}
asponge