Reputation: 1264
I have an Entity Framework 'TrackableCollection' and I want to sort it by an attribute. I have tried treating it like an IEnumerable and calling
TrackableCollection<Something>.OrderBy(q=>q.SomeValue);
but it throws an exception "Cannot implicitly covert type IOrderedEnumerable to TrackableCollection.
Anyone know how to sort a TrackableCollection?
Upvotes: 1
Views: 2572
Reputation: 8175
This is a simplifed version of Ofer Zeligs code that uses a keySelector func (like LINQ OrderBy
) instead of an explicit Comparison
delegate. Since it only uses Clear() and Add() it can be called on any Collection
object (like an ObservableCollection
or a TrackableCollection
).
public static void Sort<TSource, TKey>(this Collection<TSource> source, Func<TSource, TKey> keySelector)
{
var sorted = source.OrderBy(keySelector).ToList();
source.Clear();
foreach (var item in sorted)
source.Add(item);
}
It's used like this:
list.Sort(person => person.Name);
If you're using this on a TrackableCollection
(STE) you might want to make sure you haven't started tracking changes before sorting the list.
Upvotes: 1
Reputation: 17508
The code example Shiv Kumar refers to does not work - it doesn't compile, and even after you factor things up (like implementing generics in a lot of places), it works but buggy, since the code calls collection.Move which causes a "Index must be within the bounds of the List" exception in certain cases. The code below works correctly. The coders of STE (Self Tracking Entities) should had implemented that themselves... This is the correct code:
public static class Extensions
{
public static void Sort<T>(this TrackableCollection<T> collection, Comparison<T> comparison)
{
var comparer = new Comparer<T>(comparison);
List<T> sorted = collection.OrderBy(x=>x, comparer) .ToList();
collection.Clear();
for (int i = 0; i < sorted.Count(); i++)
collection.Add(sorted[i]);
}
}
class Comparer<T> : IComparer<T>
{
private Comparison<T> comparison;
public Comparer(Comparison<T> comparison)
{
this.comparison = comparison;
}
public int Compare(T x, T y)
{
return comparison.Invoke(x, y);
}
}
You use this code as in the previous example:
YourTrackableCollectionName.Sort((x, y) => x.YourFieldName.CompareTo(y.YourFieldName));
Upvotes: 3