Archive for June, 2009

SortableObservableCollection using LINQ and reflection

Hello Everyone!

So im taking a break on WPF today to blog about LINQ and sorting stuff.  We’ve all had to perform sorting at some point in time and sometimes a lot of adhoc, on the fly mechansims get built.  So I wanted to come up with a way to provide sorting functionality for any collection using some of the new powerful technologies like LINQ.

I have posted the code and release on Codeplex at http://sortablecollection.codeplex.com

The component makes use of a SortDescription class with a PropertyName and Direction properties.  The property name supports pointing to a value type, reference type (requires the implementation of IComparable) and also supports dot notation down your object graph to sort on child values.  You can also add multiple sort descriptions to sort by different properties.  The order in which the SortDescriptions are in the collection relates to a LINQ orderby description1, description2 so that you get a true By ThenBy calculation mechanism.

The meat of the processing is built into an extension method called BuildSorts(IEnumerable<SortDescription> sortDescriptions).  This follow most of the LINQ extension method pattern and works along with queries.  The following code is an example of how you may use the extension method

   1: List<SortDescription> sorts = new List<SortDescription>();
   2:  
   3: sorts.Add(new SortDescription() { PropertyName="LastName", Direction=SortDirection.Ascending });
   4: sorts.Add(new SortDescription() { PropertyName="FirstName", Direction=SortDirection.Ascending });
   5:  
   6: List<Person> people = dataLayer.GetPeople();
   7:  
   8: var query = from person in people
   9:             select person;
  10:  
  11: query = query.BuildSorts(sorts);
  12: //append .AsQueryable() when working with Linq to SQL
  13:  
  14: List<Person> sortedPeople = query.ToList();

 

You can use the extension method in building your master query to provide dynamic order by’s in them.

Also provided is a SortableObservableCollectionClass.  This class encapsulates the setup and usage of the extension method to provide a collection that will sort itself and also adhere to binding notification.

Here is an example of how you would use this class.

   1: SortableObservableCollection<Person> people = dataLayer.GetSortablePeople();
   2:  
   3: people.SortDescriptions.Add(new SortDescription() { PropertyName="FirstName", Direction=SortDirection.Ascending });
   4:  
   5: people.RefreshSorts();

Image that this was a property we are binding to.  By adding a sort description and calling RefreshSorts we cause the collection to re-order itself based on the sort descriptions provided.

The mechanism uses Func and Reflection behind the scenes but I have tested the performance pretty extensively and are happy with the results.

10,000 items with 2 sort descriptions takes 1-3 seconds

340,000 items with 2 sort descriptions takes 6-8 seconds

It also properly handles type sorting so strings are compared as strings, ints and ints, datetimes as datetimes and so forth.  If you are sorting on an object that doesnt have a proper default IComparable then you will need to implement that and this mechanism will use it.

I hope everyone enjoys this and have a good day!

No Comments