这是一个ObservableCollection<T>
,它会在更改时自动排序,仅在必要时触发排序,并且仅触发单个移动集合更改操作。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
namespace ConsoleApp4
{
using static Console;
public class SortableObservableCollection<T> : ObservableCollection<T>
{
public Func<T, object> SortingSelector { get; set; }
public bool Descending { get; set; }
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if (SortingSelector == null
|| e.Action == NotifyCollectionChangedAction.Remove
|| e.Action == NotifyCollectionChangedAction.Reset)
return;
var query = this
.Select((item, index) => (Item: item, Index: index));
query = Descending
? query.OrderBy(tuple => SortingSelector(tuple.Item))
: query.OrderByDescending(tuple => SortingSelector(tuple.Item));
var map = query.Select((tuple, index) => (OldIndex:tuple.Index, NewIndex:index))
.Where(o => o.OldIndex != o.NewIndex);
using (var enumerator = map.GetEnumerator())
if (enumerator.MoveNext())
Move(enumerator.Current.OldIndex, enumerator.Current.NewIndex);
}
}
//USAGE
class Program
{
static void Main(string[] args)
{
var xx = new SortableObservableCollection<int>() { SortingSelector = i => i };
xx.CollectionChanged += (sender, e) =>
WriteLine($"action: {e.Action}, oldIndex:{e.OldStartingIndex},"
+ " newIndex:{e.NewStartingIndex}, newValue: {xx[e.NewStartingIndex]}");
xx.Add(10);
xx.Add(8);
xx.Add(45);
xx.Add(0);
xx.Add(100);
xx.Add(-800);
xx.Add(4857);
xx.Add(-1);
foreach (var item in xx)
Write($"{item}, ");
}
}
}
输出:
action: Add, oldIndex:-1, newIndex:0, newValue: 10
action: Add, oldIndex:-1, newIndex:1, newValue: 8
action: Move, oldIndex:1, newIndex:0, newValue: 8
action: Add, oldIndex:-1, newIndex:2, newValue: 45
action: Add, oldIndex:-1, newIndex:3, newValue: 0
action: Move, oldIndex:3, newIndex:0, newValue: 0
action: Add, oldIndex:-1, newIndex:4, newValue: 100
action: Add, oldIndex:-1, newIndex:5, newValue: -800
action: Move, oldIndex:5, newIndex:0, newValue: -800
action: Add, oldIndex:-1, newIndex:6, newValue: 4857
action: Add, oldIndex:-1, newIndex:7, newValue: -1
action: Move, oldIndex:7, newIndex:1, newValue: -1
-800, -1, 0, 8, 10, 45, 100, 4857,