Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an observable collection with linq

Tags:

I have an observable collection and I sort it using linq. Everything is great, but the problem I have is how do I sort the actual observable collection? Instead I just end up with some IEnumerable thing and I end up clearing the collection and adding the stuff back in. This can't be good for performance. Does anyone know of a better way to do this?

like image 726
zachary Avatar asked Jun 15 '09 13:06

zachary


Video Answer


2 Answers

If you are using Silverlight 3.0, then using CollectionViewSource is the cleanest way. Refer below example: (it can be done via xaml as well)

ObservableCollection<DateTime> ecAll = new ObservableCollection<DateTime>();
CollectionViewSource sortedcvs = new CollectionViewSource();
sortedcvs.SortDescriptions.Add(new System.ComponentModel.SortDescription("Date", 
    System.ComponentModel.ListSortDirection.Ascending));
sortedcvs.Source = ecAll;
ListBoxContainer.DataContext = sortedcvs;

And in corresponding xaml set

ItemsSource="{Binding}"

for the ListBox or any ItemsControl derived control

like image 129
moonlightdock Avatar answered Sep 17 '22 12:09

moonlightdock


Since the collection doesn't provide any Sort mechanism, this is probably the most practical option. You could implement a sort manually using Move etc, but it will probably be slower than doing in this way.

    var arr = list.OrderBy(x => x.SomeProp).ToArray();
    list.Clear();
    foreach (var item in arr) {
        list.Add(item);
    }

Additionally, you might consider unbinding any UI elements while sorting (via either approach) you only pay to re-bind once:

Interestingly, if this was BindingList<T>, you could use RaiseListChangedEvents to minimise the number of notifications:

    var arr = list.OrderBy(x => x).ToArray();
    bool oldRaise = list.RaiseListChangedEvents;
    list.RaiseListChangedEvents = false;
    try {
        list.Clear();
        foreach (var item in arr) {
            list.Add(item);
        }
    } finally {
        list.RaiseListChangedEvents = oldRaise;
        if (oldRaise) list.ResetBindings();
    }
like image 32
Marc Gravell Avatar answered Sep 16 '22 12:09

Marc Gravell