Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting List vs. ObservableCollection

I have found out that I am "doing WPF wrong" and frustratingly must overhaul alot of my code.

How could I convert the following:

public static class SortName 
    {
       public static  int Compare(Person a, Person b)
        {
            return a.Name.CompareTo(b.Name);
        }

    }

and I call it like:

list.Sort(SortName.Compare);

to the format required for ObservableCollection. And how would I call it. So far i've tried this following based on what I read here

class ObservableCollectionSortName<T> : ObservableCollection<T> 
{
    public int Compare (Person a, Person b)
    {
        return a.Name.CompareTo(b.Name);
    }
}
like image 672
baron Avatar asked Dec 03 '22 13:12

baron


2 Answers

The observable collection doesn't implement sorting, for the simple reason that every time an item moves from one location in the list to another the collection raises an event. That would be great for watching animations of the sort algorithm in action, but it would sort of suck for, you know, sorting.

There are two ways to do this; they're very similar, and both start by sorting the items outside their observable collection, e.g. if _Fruits is an ObservableCollection<Fruit>, and you've defined an IComparer<Fruit> for the sort, you'd do:

var sorted = _Fruits.OrderBy(x => x, new FruitComparer());

That creates a new IEnumerable<Fruit> that, when you iterate over it, will have the objects in the new order. There are two things you can do with this.

One is to create a new collection, replace the old one, and force any items control(s) in the UI to rebind to it:

_Fruits = new ObservableCollection<Fruit>(sorted);
OnPropertyChanged("Fruits");

(This assumes that your class implements INotifyPropertyChanged in the usual way.)

The other is to create a new sorted list, and then use it to move the items in your collection:

int i = 0;
foreach (Fruit f in sorted)
{
   _Fruits.MoveItem(_Fruits.IndexOf(f), i);
   i++;
}

The second approach is something I'd only try if I had a really serious commitment to not rebinding the items controls, because it's going to raise a ton of collection-changed events.

like image 79
Robert Rossney Avatar answered Dec 28 '22 04:12

Robert Rossney


If the main reason for sorting your observable collection is to display the data in a sorted list to the user and not for performance reasons (i.e. faster access) then a CollectionViewSource can be used. Bea Stollnitz has a good description on her blog of how to use the CollectionViewSource to implement sorting and grouping of collections for the UI.

This may help as it means you will not have to implement sorting on your observable collection and worry about the performance hits indicated by Robert of sending the INotifyCollectionChanged. However it will allow for the displaying of items in a sorted order in the UI.

like image 25
mattythomas2000 Avatar answered Dec 28 '22 05:12

mattythomas2000