通过 C# 对 ObservableCollection<string> 进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19112922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sort ObservableCollection<string> through C#
提问by Bishan
I have below ObservableCollection<string>
. I need to sortthis alphabetically.
我有以下ObservableCollection<string>
。我需要进行排序按字母顺序这一点。
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"
};
I tried _animals.OrderByDescending
. But I don't know how to use it correctly.
我试过了_animals.OrderByDescending
。但我不知道如何正确使用它。
_animals.OrderByDescending(a => a.<what_is_here_?>);
How can I do this?
我怎样才能做到这一点?
采纳答案by Sergey Brunov
Introduction
介绍
Basically, if there is a need to display a sorted collection, please consider using the CollectionViewSource
class: assign ("bind") its Source
property to the source collection — an instance of the ObservableCollection<T>
class.
基本上,如果需要显示排序集合,请考虑使用CollectionViewSource
类:将其Source
属性分配(“绑定”)到源集合——ObservableCollection<T>
类的一个实例。
The idea is that CollectionViewSource
class provides an instance of the CollectionView
class. This is kind of "projection" of the original (source) collection, but with applied sorting, filtering, etc.
这个想法是,CollectionViewSource
类提供的实例CollectionView
类。这是原始(源)集合的一种“投影”,但应用了排序、过滤等。
References:
参考:
Live Shaping
实时整形
WPF 4.5 introduces "Live Shaping" feature for CollectionViewSource
.
WPF 4.5 为CollectionViewSource
.
References:
参考:
- WPF 4.5 New Feature: Live Shaping.
- CollectionViewSource.IsLiveSorting Property.
- Repositioning data as the data's values change (Live shaping).
Solution
解决方案
If there still a need to sort an instance of the ObservableCollection<T>
class, here is how it can be done.
The ObservableCollection<T>
class itself does not have sort method. But, the collection could be re-created to have items sorted:
如果仍然需要对类的实例进行排序ObservableCollection<T>
,这里是如何完成的。在ObservableCollection<T>
类本身不具有排序方法。但是,可以重新创建集合以对项目进行排序:
// 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));
Additional details
额外细节
Please note that OrderBy()
and OrderByDescending()
methods (as other LINQ–extension methods) do not modifythe source collection! They instead create a new sequence(i.e. a new instance of the class that implements IEnumerable<T>
interface). Thus, it is necessary to re-create the collection.
请注意OrderBy()
和OrderByDescending()
方法(与其他 LINQ 扩展方法一样)不会修改源集合!相反,它们创建了一个新序列(即实现IEnumerable<T>
接口的类的新实例)。因此,有必要重新创建集合。
回答by manji
The argument to OrderByDescending
is a function returning a key to sort with. In your case, the key is the string itself:
to 的参数OrderByDescending
是一个返回要排序的键的函数。在您的情况下,关键是字符串本身:
var result = _animals.OrderByDescending(a => a);
If you wanted to sort by length for example, you'll write:
例如,如果你想按长度排序,你会写:
var result = _animals.OrderByDescending(a => a.Length);
回答by Bram Van Strydonck
_animals.OrderByDescending(a => a.<what_is_here_?>);
If animals would be a list of object Animal, you could use a property to order the list.
如果动物是对象 Animal 的列表,您可以使用属性来对列表进行排序。
public class Animal
{
public int ID {get; set;}
public string Name {get; set;}
...
}
ObservableCollection<Animal> animals = ...
animals = animals.OrderByDescending(a => a.Name);
回答by Marco
I know this is an old question, but is the first google result for "sort observablecollection" so thought it worth to leave my two cent.
我知道这是一个老问题,但它是“排序可观察集合”的第一个谷歌结果,所以我认为值得留下我的两分钱。
The way
道路
The way I would go is to build a List<>
starting from the ObservableCollection<>
, sort it (through its Sort()
method, more on msdn) and when the List<>
has been sorted, reorder the ObservableCollection<>
with the Move()
method.
我要走的方法是List<>
从 开始ObservableCollection<>
,对其进行排序(通过其Sort()
方法,更多关于 msdn),并在对List<>
进行排序后,ObservableCollection<>
使用该Move()
方法重新排序。
The code
编码
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);
}
}
The test
考试
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 elements have been sorted
for (int i = 0; i < maxValue; i++)
{
Assert.AreEqual(i, observableCollection[i]);
}
}
Notes
笔记
This is just a proof of concept, showing how to sort an ObservableCollection<>
without breaking the bindings on items.The sort algorithm has room for improvements and validations (like index checking as pointed out here).
这仅仅是一个概念验证,展示如何排序的ObservableCollection<>
,而不打破items.The排序算法的绑定有改进的空间和验证(如索引检查为指出,在这里)。
回答by John Leone
I looked at these, I was getting it sorted, and then it broke the binding, as above. Came up with this solution, though simpler than most of yours, it appears to do what I want to,,,
我看着这些,我正在整理它,然后它打破了绑定,如上所述。想出了这个解决方案,虽然比你的大多数解决方案简单,但它似乎可以做我想做的,,,
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;
}
回答by Tim Pohlmann
/// <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);
}
}
This solution is based on Marco's answer. I had some problemswith his solution and therefore improved it by only calling Move
if the index actually changed. This should improve performance and also fix the linked issue.
此解决方案基于Marco 的回答。我对他的解决方案有一些问题,因此仅Move
在索引实际更改时才调用来改进它。这应该可以提高性能并解决相关问题。
回答by Lance
I created an extension method to the ObservableCollection
我为 ObservableCollection 创建了一个扩展方法
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);
}
}
It seems to work and you don't need to implement IComparable
它似乎工作,你不需要实现 IComparable
回答by SabariMurugan Sivakumar
myObservableCollection.ToList().Sort((x, y) => x.Property.CompareTo(y.Property));
回答by Shimmy Weitzhandler
This is an ObservableCollection<T>
, that automatically sorts itself upon a change, triggers a sort only when necessary, and only triggers a single move collection change action.
这是一个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}, ");
}
}
}
Output:
输出:
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,
回答by Kairat Koibagarov
I did a sort on a certain class field (distance).
我对某个类字段(距离)进行了排序。
public class RateInfo
{
public string begin { get; set; }
public string end { get; set; }
public string price { get; set; }
public string comment { get; set; }
public string phone { get; set; }
public string ImagePath { get; set; }
public string what { get; set; }
public string distance { get; set; }
}
public ObservableCollection<RateInfo> Phones { get; set; }
public List<RateInfo> LRate { get; set; }
public ObservableCollection<RateInfo> Phones { get; set; }
public List<RateInfo> LRate { get; set; }
......
foreach (var item in ph)
{
LRate.Add(new RateInfo { begin = item["begin"].ToString(), end = item["end"].ToString(), price = item["price"].ToString(), distance=kilom, ImagePath = "chel.png" });
}
LRate.Sort((x, y) => x.distance.CompareTo(y.distance));
foreach (var item in LRate)
{
Phones.Add(item);
}