Алгоритм сортировки CollectionViewSource
Как изменить алгоритм сортировки CollectionViewSource? Фактически, я обнаружил, что алгоритм сортировки CollectionViewSource не стабилен. И я хочу использовать стабильный алгоритм на CollectionViewSource. Как я могу это сделать?
2 ответа
Мне удалось получить стабильную сортировку с помощью пользовательского Comparer, но это похоже на большой взлом...
Так же, как предложил Бенджамин, я получаю ListCollectionView из коллекции и устанавливаю его свойство CustomSort с помощью моего пользовательского Comparer. Разница лишь в том, что я передаю коллекцию в Comparer при ее создании.
private void Sorting(IEnumerable collection)
{
var view = CollectionViewSource.GetDefaultView(collection) as ListCollectionView;
if (view != null)
{
view.CustomSort = new StableComparer(collection);
}
}
Затем в моем пользовательском Comparer я использую коллекцию в методе Compare только для возврата к индексам элементов, когда сравнение возвращает ноль (они одинаковы или имеют одинаковое значение).
public class StableComparer : IComparer
{
public IEnumerable Collection { get; set; }
public StableComparer(IEnumerable collection)
{
Collection = collection;
}
public int Compare(object x, object y)
{
IComparable x_Comparable = x as IComparable;
IComparable y_Comparable = y as IComparable;
if (x_Comparable != null && y_Comparable != null)
{
var comparison = x_Comparable.CompareTo(y_Comparable);
// A zero value means x and y are equivalent for sorting, and they could
// be rearranged by an unstable sorting algorithm
if (comparison == 0 && Collection != null)
{
// IndexOf is an extension method for IEnumerable (not included)
var x_Index = Collection.IndexOf(x);
var y_Index = Collection.IndexOf(y);
// By comparing their indexes in the original collection, we get to
// preserve their relative order
if (x_Index != -1 && y_Index != -1)
comparison = x_Index.CompareTo(y_Index);
}
return comparison;
}
return 0;
}
}
Я все еще тестирую это, поэтому я не могу гарантировать, что это будет работать постоянно... Одной из проблем, например, будет обновление свойства Collection внутри Comparer. Или поддерживая два вида сортировки.
Но я думаю, что идея ясна, хотя и хакерская, как я уже сказал.
Возможно, вы захотите проверить, как реализовать свою собственную логику сортировки.
Короче, установите ваш компаратор так:
private void Sort(object sender, RoutedEventArgs args)
{
BlogPosts posts = (BlogPosts)(this.Resources["posts"]);
ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(posts));
lcv.CustomSort = new SortPosts();
}
И реализовать это так:
public class SortPosts : IComparer
{
public int Compare(object x, object y)
{
(…)
}
}