How to sort an ObservableCollection
In Silverlight and WPF, Observable collection is the preferable bindable data source to element like Datagrid, list boxes etc since it supports INotifyPropertyChanged <https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx> interface which enables the host elements to notify the change in the collection.
Unlike List and other collection, ObservableCollection<T> does not support inbuilt sorting and most of the user built applications demand sorting. So, in this article, we will see different ways of sorting an observable collection.
I will use the same class used before. Additionally to enable sorting, I have implemented the IComparable interface
public class Data : IComparable
{
public string FirstName get; set;
public string LastName get; set;
public int Age get; set;
public bool Available get; set;
public DateTime DOJ get; set;
public int CompareTo(object obj)
{
Data cric = obj as Data;
if (cric == null)
{
throw new ArgumentException("Object is not Cricketer");
}
return this.FirstName.CompareTo(cric.FirstName);
}
}
As shown above, compareTo method is implemented to sort data.
Next I will create a collection of some well known cricketers using ObservableCollection< Data>
private ObservableCollection<Data> LoadObservableData()
{
ObservableCollection<Data> cricketers = new ObservableCollection<Data>();
cricketers.Add(new Data()
{
FirstName = "Mahi",
LastName = "Dhoni",
Age = 31,
Available = false,
DOJ = new DateTime(2001, 11, 10)
});
cricketers.Add(new Data()
{
FirstName = "Sarin",
LastName = "Mall",
Age = 26,
Available = true,
DOJ = new DateTime(2011, 05, 07)
});
cricketers.Add(new Data()
{
FirstName = "Sachin",
LastName = "Tendulkar",
Age = 39,
Available = true,
DOJ = new DateTime(1989, 01, 08)
});
cricketers.Add(new Data()
{
FirstName = "Viru",
LastName = "Sehwag",
Age = 34,
Available = true,
DOJ = new DateTime(1998, 01, 26)
});
return cricketers;
}
In my first technique I would extend the Linq order by with a simple lambda expression.
ObservableCollection<Data> crics = new ObservableCollection<Data>(LoadObservableData().OrderBy(stars => stars.Age));
Disadvantage of this method is that it creates a new collection to sort data. Performance would be negligible with small collections but as the data grows, creating and transferring data from the new collection to the original collection would turn expensive. Small advantage with this approach is unlimited flexibility of defining your own sorting logic using lambda expressions. As defined in the implementation of IComparable, cricketers are sorted by age. But we can override this implementation to sort by some other property as
ObservableCollection<Data> crics = new ObservableCollection<Data>(LoadObservableData().OrderBy(stars => stars.FirstName));
Second method of sorting is more or less similar to the first method. In this method, I would be using the inbuilt sorting technique of List<T>
List<Data> sorteddata = new List<Data>(LoadCollectionData());
sorteddata.Sort();
ObservableCollection<Data> crics = new ObservableCollection<Data>(sorteddata);
But again the disadvantage would be creation of two collections.
Third option is to implement our own sorting method. In this method, I have used the LINQ extension to bubble sort ObservableCollection<T>. This method has the limitation of sorting only the generic collections supporting IComparable.
public static class ListExtension
{
public static void BubbleSort(this IList o)
{
for (int i = o.Count - 1; i >= 0; i--)
{
for (int j = 1; j <= i; j++)
{
object o1 = o[j - 1];
object o2 = o[j];
if (((IComparable)o1).CompareTo(o2) > 0)
{
o.Remove(o1);
o.Insert(j, o1);
}
}
}
}
}
Data is sorted by calling the extension method as shown below
List<Data