0

I have following TracefieldPartProgramClass

public class TracefieldPartProgramClass
{
    public TracefieldPartProgramClass() { }
    public ObservableCollection<Tuple<string, object, object>> obcTraceFieldPartProgram = new ObservableCollection<Tuple<string, object, object>>();
}

I use it to make the following collection:

ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>();

now after having filled it I want to be able to sort as I want (say on the Tracefield[0]). So I implemented this:

private ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> SortOnTracefield(ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> obcToSort)
{
var obcSorted = new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>();
obcSorted = obcToSort.OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString());<--- this is where I get the error
return obcSorted;

}

but when I do it, I get this error:

Error CS0266 Cannot implicitly convert type 'System.Linq.IOrderedEnumerable' to 'System.Collections.ObjectModel.ObservableCollection'. An explicit conversion exists (are you missing a cast?)

Patrick
  • 3,073
  • 2
  • 22
  • 60

3 Answers3

3

Try this one:

private ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> SortOnTracefield(ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass> obcToSort)
{
    var sorted = obcToSort.OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString();
    return new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>(sorted);
}

You can pass an IEnumerable to the observable collection's constructor.


However, that returns a new instance of the collection. So, if the unsorted instance was bound to the GUI, that may not update your GUI. Another approch to support sorting is to use the ICollectionView.


The SO question how-do-i-sort-an-observable-collection may be intersting for you too. The following extension method can be used for sorting ObservableCollections without recreation:

static class Extensions
{
    public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable
    {
        List<T> sorted = collection.OrderBy(x => x).ToList();
        for (int i = 0; i < sorted.Count(); i++)
            collection.Move(collection.IndexOf(sorted[i]), i);
    }
}

However, your TracefieldPartProgramClass class needs to implement IComparable or you'll need to implement a custom IComparer<TracefieldPartProgramClass> and pass it the Sort method.

Community
  • 1
  • 1
JanDotNet
  • 3,746
  • 21
  • 30
2

Enumerable.OrderBy doesn't return an ObservableCollection but an IEnumerable<T>, you can create a new with the List<T> constructor:

var obcSortedList = obcToSort
    .OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString())
    .ToList();  
var obcSorted = new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>(obcSortedList);
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Why do you use the IList constructor instead of the IEnumerable one? Does that have any performance benefits? – Domysee May 31 '16 at 09:31
  • 1
    @Domysee: the [`List` constructor](http://referencesource.microsoft.com/#mscorlib/system/collections/objectmodel/collection.cs,f89eec626d3cfff1) is a no-op, the `IEnumerable` constructor will create a list anyway by enumerating all elements. So you can use both. – Tim Schmelter May 31 '16 at 09:33
  • However the `List` constructor also creates a copy of the passed list ([source](http://referencesource.microsoft.com/#System/compmod/system/collections/objectmodel/observablecollection.cs,f63ea2601f5edbbb)), so `IEnumerable` constructor looks more appropriate to me. – Ivan Stoev May 31 '16 at 09:39
  • @IvanStoev: haven't seen the comment about the VSWhidbey bug 562681, so you're right. Then i'd also prefer the `IEnumerable` constructor if i don't have a list already. – Tim Schmelter May 31 '16 at 09:51
2

As the error says, you are trying to assign an IOrderedEnumerable to a variable of type ObservableCollection, which is not possible.

But luckily, ObservableCollection has a constructor that takes an IEnumerable and prefills it with the items of that IEnumerable.

So, in order to make that error disappear, use that:

var sortedEnumerable = obcToSort.OrderBy(w => w.obcTraceFieldPartProgram[0].Item3.ToString());
obcSorted = new ObservableCollection<EasyRunBinSerializableData.TracefieldPartProgramClass>(sortedEnumerable );
Domysee
  • 12,718
  • 10
  • 53
  • 84