Patrick
Patrick

Reputation: 2593

How to cope with an Observable collection of classes

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?)

Upvotes: 0

Views: 497

Answers (3)

JanDotNet
JanDotNet

Reputation: 4016

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.

Upvotes: 3

Domysee
Domysee

Reputation: 12846

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 );

Upvotes: 2

Tim Schmelter
Tim Schmelter

Reputation: 460238

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);

Upvotes: 2

Related Questions