Time ago i had to implement a sortable observable collection that was able to sort its members based on different parameters.
After long and long searching i found this code, and i report it here so it can be useful for readers too.
You can use the SortableObservableCollection in this way:
public class Person { public string Name { get; set; } public int Age { get; set; } } public class PersonCollection : SortableObservableCollection { public PersonCollection() { [...fill collection...] this.Sort(x => x.Name, ListSortDirection.Ascending); } }
Source code is the following…
/* * samples: * //sort ascending * MySortableList.Sort(x => x.Name, ListSortDirection.Ascending); * * //sort descending * MySortableList.Sort(x => x.Name, ListSortDirection.Descending); */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; namespace Common.WPF { public class SortableObservableCollection<T> : ObservableCollection<T> { public void Sort<TKey>(Func<T,TKey> keySelector, System.ComponentModel.ListSortDirection direction) { switch (direction) { case System.ComponentModel.ListSortDirection.Ascending: { ApplySort(Items.OrderBy(keySelector)); break; } case System.ComponentModel.ListSortDirection.Descending: { ApplySort(Items.OrderByDescending(keySelector)); break; } } } public void Sort<TKey>(Func<T,TKey> keySelector, IComparer<TKey> comparer) { ApplySort(Items.OrderBy(keySelector, comparer)); } private void ApplySort(IEnumerable<T> sortedItems) { var sortedItemsList = sortedItems.ToList(); foreach (var item in sortedItemsList) { Move(IndexOf(item), sortedItemsList.IndexOf(item)); } } } }
What a great blog
How to make this class as generic ?
like
public class SortableObservableCollection : ObservableCollection where T : EntityObject
I’m sorry, i don’t know how to do that. Try to ask to stackoverflow, maybe they can help you more.
Hi there Mesta,
thanks for the solution.
I modified you version to be usable within a protable class Library (basically the ListSortDirection is not avaible for me).
I also created two descants. See below.
/*
* samples:
* //sort ascending
* MySortableList.Sort(x => x.Name, SortDirection.Ascending);
*
* //sort descending
* MySortableList.Sort(x => x.Name, SortDirection.Descending);
*/
public enum SortDirection
{
Ascending,
Descending
}
public class SortableObservableCollection : ObservableCollection
{
#region Consts, Fields, Events
#endregion
#region Methods
public void Sort(Func keySelector, SortDirection direction)
{
switch (direction)
{
case SortDirection.Ascending:
{
applySort(Items.OrderBy(keySelector));
break;
}
case SortDirection.Descending:
{
applySort(Items.OrderByDescending(keySelector));
break;
}
}
}
public void Sort(Func keySelector, IComparer comparer)
{
applySort(Items.OrderBy(keySelector, comparer));
}
private void applySort(IEnumerable sortedItems)
{
var sortedItemsList = sortedItems.ToList();
foreach (var item in sortedItemsList)
{
Move(IndexOf(item), sortedItemsList.IndexOf(item));
}
}
#endregion
}
///
/// Provides automatic sorting, when items are added/removed
///
///
public class SortedObservableCollection : SortableObservableCollection
{
#region Consts, Fields, Events
private readonly IComparer _comparer;
#endregion
#region Methods
public SortedObservableCollection(IComparer comparer)
{
Condition.Requires(comparer, “comparer”).IsNotNull();
_comparer = comparer;
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
Sort();
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
Sort();
}
public void Sort()
{
Sort(item => item, _comparer);
}
#endregion
}
///
/// Whenever a property of the item changed, a sorting will be issued.
///
///
public class SortedObservableCollectionEx : SortedObservableCollection where T : class , INotifyPropertyChanged
{
#region Consts, Fields, Events
#endregion
#region Methods
public SortedObservableCollectionEx(IComparer comparer)
: base(comparer)
{
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
if (item != null)
{
item.PropertyChanged += handleItemPropertyChanged;
}
}
protected override void RemoveItem(int index)
{
T item = this[index];
if (item != null)
{
item.PropertyChanged -= handleItemPropertyChanged;
}
base.RemoveItem(index);
}
private void handleItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
Sort();
}
#endregion
}
Thanks for sharing, i will update the code as soon as possible.
Tanks, its really help me.