sortingObservableCollection <string> C#
我有下面的ObservableCollection<string>
。 我需要按字母顺序sorting。
private ObservableCollection<string> _animals = new ObservableCollection<string> { "Cat", "Dog", "Bear", "Lion", "Mouse", "Horse", "Rat", "Elephant", "Kangaroo", "Lizard", "Snake", "Frog", "Fish", "Butterfly", "Human", "Cow", "Bumble Bee" };
我试过_animals.OrderByDescending
。 但我不知道如何正确使用它。
_animals.OrderByDescending(a => a.<what_is_here_?>);
我该怎么做?
介绍
基本上,如果需要显示已sorting的集合,请考虑使用CollectionViewSource
类:将其Source
属性分配(“绑定”)到源集合 – ObservableCollection<T>
类的实例。
这个想法是CollectionViewSource
类提供了CollectionViewSource
类的一个实例 。 这是原始(源)集合的“投影”,但应用了分类,过滤等。
参考文献:
- 如何使用XAML中的视图对数据进行sorting和分组
- WPF的CollectionViewSource 。
实况塑造
WPF 4.5为CollectionViewSource
引入了“实时整形”function。
参考文献:
- WPF 4.5新function:实时成形 。
- CollectionViewSource.IsLiveSorting属性 。
- 随着数据值的变化重新定位数据(实时整形) 。
解
如果仍然需要对ObservableCollection<T>
类的实例进行sorting,那么可以这样做。 ObservableCollection<T>
类本身没有sorting方法。 但是,可以重新创build集合以使项目sorting:
// Animals property setter must raise "property changed" event to notify binding clients. // See INotifyPropertyChanged interface for details. Animals = new ObservableCollection<string> { "Cat", "Dog", "Bear", "Lion", "Mouse", "Horse", "Rat", "Elephant", "Kangaroo", "Lizard", "Snake", "Frog", "Fish", "Butterfly", "Human", "Cow", "Bumble Bee" }; ... Animals = new ObservableCollection<string>(Animals.OrderBy(i => i));
额外细节
请注意, OrderBy()
和OrderByDescending()
方法(与其他LINQ扩展方法一样) 不会修改源集合! 而是创build一个新的序列 (即实现IEnumerable<T>
接口的类的新实例)。 因此,有必要重新创build集合。
我知道这是一个古老的问题,但它是第一个谷歌的结果“sortingobservablecollection”,所以认为值得离开我的两分。
方式
我会走的方式是从ObservableCollection<>
List<>
开始build立一个List<>
,对其进行Sort()
通过它的Sort()
方法, 在msdn上进行sorting),当List<>
已经sorting时,用ObservableCollection<>
Move()
方法。
代码
public static void Sort<T>(this ObservableCollection<T> collection, Comparison<T> comparison) { var sortableList = new List<T>(collection); sortableList.Sort(comparison); for (int i = 0; i < sortableList.Count; i++) { collection.Move(collection.IndexOf(sortableList[i]), i); } }
考试
public void TestObservableCollectionSortExtension() { var observableCollection = new ObservableCollection<int>(); var maxValue = 10; // Populate the list in reverse mode [maxValue, maxValue-1, ..., 1, 0] for (int i = maxValue; i >= 0; i--) { observableCollection.Add(i); } // Assert the collection is in reverse mode for (int i = maxValue; i >= 0; i--) { Assert.AreEqual(i, observableCollection[maxValue - i]); } // Sort the observable collection observableCollection.Sort((a, b) => { return a.CompareTo(b); }); // Assert element have been sorted for (int i = 0; i < maxValue; i++) { Assert.AreEqual(i, observableCollection[i]); } }
_animals.OrderByDescending(a => a.<what_is_here_?>);
如果动物是动物对象列表,则可以使用属性来排列列表。
public class Animal { public int ID {get; set;} public string Name {get; set;} ... } ObservableCollection<Animal> animals = ... animals = animals.OrderByDescending(a => a.Name);
OrderByDescending
的参数是一个返回键sorting的函数。 在你的情况下,关键是string本身:
var result = _animals.OrderByDescending(a => a);
如果你想按照时间sorting,你会写:
var result = _animals.OrderByDescending(a => a.Length);
我看着这些,我正在分类,然后打破了绑定,如上所述。 拿出这个解决scheme,虽然比你们大多数都简单,但它似乎是做我想要的,
public static ObservableCollection<string> OrderThoseGroups( ObservableCollection<string> orderThoseGroups) { ObservableCollection<string> temp; temp = new ObservableCollection<string>(orderThoseGroups.OrderBy(p => p)); orderThoseGroups.Clear(); foreach (string j in temp) orderThoseGroups.Add(j); return orderThoseGroups; }
我为ObservableCollection创build了一个扩展方法
public static void MySort<TSource,TKey>(this ObservableCollection<TSource> observableCollection, Func<TSource, TKey> keySelector) { var a = observableCollection.OrderBy(keySelector).ToList(); observableCollection.Clear(); foreach(var b in a) { observableCollection.Add(b); } }
这似乎工作,你不需要实现IComparable
myObservableCollection.ToList().Sort((x, y) => x.Property.CompareTo(y.Property));
/// <summary> /// Sorts the collection. /// </summary> /// <typeparam name="T">The type of the elements of the collection.</typeparam> /// <param name="collection">The collection to sort.</param> /// <param name="comparison">The comparison used for sorting.</param> public static void Sort<T>(this ObservableCollection<T> collection, Comparison<T> comparison = null) { var sortableList = new List<T>(collection); if (comparison == null) sortableList.Sort(); else sortableList.Sort(comparison); for (var i = 0; i < sortableList.Count; i++) { var oldIndex = collection.IndexOf(sortableList[i]); var newIndex = i; if (oldIndex != newIndex) collection.Move(oldIndex, newIndex); } }
这个解决scheme是基于Marco的回答 。 我的解决scheme存在一些问题 ,因此只有在索引实际改变时才调用Move
改进它。 这应该提高性能,并解决相关问题。
这是一个ObservableCollection<T>
,在更改时自动sorting,仅在必要时触发sorting,并且仅触发单个移动集合更改操作。
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 (e.Action != NotifyCollectionChangedAction.Reset && e.Action != NotifyCollectionChangedAction.Move && SortingSelector != null) { 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,