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 ObservableCo
The problem with sorting an ObservableCollection is that every time you change the collection, an event will get fired off. So for a sort that is removing items from one position and adding them to another, you will end up having a ton of events firing.
I think you're best bet is to just insert the stuff into the ObservableCollection in the proper order to begin with. Removing items from the collection won't effect ordering. I whipped up a quick extension method to illustrate
public static void InsertSorted(this ObservableCollection collection, T item, Comparison comparison)
{
if (collection.Count == 0)
collection.Add(item);
else
{
bool last = true;
for (int i = 0; i < collection.Count; i++)
{
int result = comparison.Invoke(collection[i], item);
if (result >= 1)
{
collection.Insert(i, item);
last = false;
break;
}
}
if (last)
collection.Add(item);
}
}
So if you were to use strings (for instance), the code would look like this
ObservableCollection strs = new ObservableCollection();
Comparison comparison = new Comparison((s1, s2) => { return String.Compare(s1, s2); });
strs.InsertSorted("Mark", comparison);
strs.InsertSorted("Tim", comparison);
strs.InsertSorted("Joe", comparison);
strs.InsertSorted("Al", comparison);
Edit
You can keep the calls identical if you extend the ObservableCollection and supply your own insert/add methods. Something like this:
public class BarDataCollection : ObservableCollection
{
private Comparison _comparison = new Comparison((bd1, bd2) => { return DateTime.Compare(bd1.StartDate, bd2.StartDate); });
public new void Insert(int index, BarData item)
{
InternalInsert(item);
}
protected override void InsertItem(int index, BarData item)
{
InternalInsert(item);
}
public new void Add(BarData item)
{
InternalInsert(item);
}
private void InternalInsert(BarData item)
{
if (Items.Count == 0)
Items.Add(item);
else
{
bool last = true;
for (int i = 0; i < Items.Count; i++)
{
int result = _comparison.Invoke(Items[i], item);
if (result >= 1)
{
Items.Insert(i, item);
last = false;
break;
}
}
if (last)
Items.Add(item);
}
}
}
The insert index is ignored.
BarData db1 = new BarData(DateTime.Now.AddDays(-1));
BarData db2 = new BarData(DateTime.Now.AddDays(-2));
BarData db3 = new BarData(DateTime.Now.AddDays(1));
BarData db4 = new BarData(DateTime.Now);
BarDataCollection bdc = new BarDataCollection();
bdc.Add(db1);
bdc.Insert(100, db2);
bdc.Insert(1, db3);
bdc.Add(db4);