how to sort ObservableCollection

Souvik Basu picture Souvik Basu · Sep 2, 2011 · Viewed 38.1k times · Source

I have a an ObservableCollection and a WPF UserControl is Databound to it. The Control is a graph that shows a vertical bar for each item of type BarData in the ObservableCollection.

ObservableCollection<BarData>

class BarData
{
   public DateTime StartDate {get; set;}
   public double MoneySpent {get; set;}
   public double TotalMoneySpentTillThisBar {get; set;}
}

Now I want to sort out the ObservableCollection based on StartDate so that the BarData's will be in increasing order of StartDate in the collection. Then I can calculate values of TotalMoneySpentTillThisBar in each BarData like this -

var collection = new ObservableCollection<BarData>();
//add few BarData objects to collection
collection.Sort(bar => bar.StartData);    // this is ideally the kind of function I was looking for which does not exist 
double total = 0.0;
collection.ToList().ForEach(bar => {
                                     bar.TotalMoneySpentTillThisBar = total + bar.MoneySpent;
                                     total = bar.TotalMoneySpentTillThisBar; 
                                   }
                            );

I know I can use ICollectionView to sort, filter data for veiwing but that does not change the actual collection. I need to sort the actual collection so that I can calculate TotalMoneySpentTillThisBar for each item. Its value depends on order of items in colection.

Thanks.

Answer

Gregfr picture Gregfr · Sep 2, 2011

hummm first question I have for you is: is it really important that your ObservableCollection is sorted, or is what you really want is to have the display in GUI sorted?

I assume that the aim is to have a sorted display that will be updated "real time". Then I see 2 solutions

  1. get the ICollectionView of your ObservableCollection and sort it, as explained here http://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/

  2. bind your ObservableCollection to a CollectionViewsource, add a sort on it, then use thatCollectionViewSource as the ItemSource of a ListView.

i.e:

add this namespace

xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"

then

<CollectionViewSource x:Key='src' Source="{Binding MyObservableCollection, ElementName=MainWindowName}">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="MyField" />
    </CollectionViewSource.SortDescriptions>

</CollectionViewSource>

and bind like this

<ListView ItemsSource="{Binding Source={StaticResource src}}" >