Sort ObservableCollection C #

Tengo debajo de ObservableCollection . Necesito ordenar esto alfabéticamente.

 private ObservableCollection _animals = new ObservableCollection { "Cat", "Dog", "Bear", "Lion", "Mouse", "Horse", "Rat", "Elephant", "Kangaroo", "Lizard", "Snake", "Frog", "Fish", "Butterfly", "Human", "Cow", "Bumble Bee" }; 

Intenté _animals.OrderByDescending . pero no sé cómo usarlo correctamente.

 _animals.OrderByDescending(a => a.); 

Cómo puedo hacer esto ?

Introducción

Básicamente, si es necesario mostrar una colección ordenada, considere usar la clase CollectionViewSource : asigne (“bind”) su propiedad Source a la colección fuente, una instancia de la clase ObservableCollection .

La idea es que la clase CollectionViewSource proporciona una instancia de la clase CollectionView . Esto es una especie de “proyección” de la colección original (fuente), pero con clasificación aplicada, filtrado, etc.

Referencias

  • Cómo: ordenar y agrupar datos usando una vista en XAML .
  • CollectionViewSource de WPF .

Live Shaping

WPF 4.5 presenta la función “Live Shaping” para CollectionViewSource .

Referencias

  • WPF 4.5 Nueva característica: Live Shaping .
  • Propiedad CollectionViewSource.IsLiveSorting .
  • Reposicionamiento de datos a medida que cambian los valores de los datos (configuración en vivo) .

Solución

Si todavía hay una necesidad de ordenar una instancia de la clase ObservableCollection , aquí es cómo se puede hacer. La clase ObservableCollection sí misma no tiene método de clasificación. Sin embargo, la colección podría volver a crearse para ordenar los elementos:

 // Animals property setter must raise "property changed" event to notify binding clients. // See INotifyPropertyChanged interface for details. Animals = new ObservableCollection { "Cat", "Dog", "Bear", "Lion", "Mouse", "Horse", "Rat", "Elephant", "Kangaroo", "Lizard", "Snake", "Frog", "Fish", "Butterfly", "Human", "Cow", "Bumble Bee" }; ... Animals = new ObservableCollection(Animals.OrderBy(i => i)); 

Detalles adicionales

Tenga en cuenta que los OrderBy() y OrderByDescending() (como otros métodos de extensión LINQ) no modifican la colección de origen. En su lugar, crean una nueva secuencia (es decir, una nueva instancia de la clase que implementa la IEnumerable ). Por lo tanto, es necesario volver a crear la colección.

Sé que es una vieja pregunta, pero es el primer resultado de google para “ordenar una colección observable”, así que pensé que valía la pena dejar mi dos centavos.

La manera

La forma en que iría es crear una List<> partir de ObservableCollection<> , ordenarla (a través de su método Sort() , más en msdn ) y cuando se haya ordenado la List<> , vuelva a ordenar la ObservableCollection<> con la Método Move()

El código

 public static void Sort(this ObservableCollection collection, Comparison comparison) { var sortableList = new List(collection); sortableList.Sort(comparison); for (int i = 0; i < sortableList.Count; i++) { collection.Move(collection.IndexOf(sortableList[i]), i); } } 

La prueba

 public void TestObservableCollectionSortExtension() { var observableCollection = new ObservableCollection(); 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]); } } 

Creé un método de extensión para ObservableCollection

 public static void MySort(this ObservableCollection observableCollection, Func keySelector) { var a = observableCollection.OrderBy(keySelector).ToList(); observableCollection.Clear(); foreach(var b in a) { observableCollection.Add(b); } } 

Parece que funciona y no necesita implementar IComparable

Miré esto, lo estaba ordenando, y luego rompió el enlace, como se indica arriba. Terminó con esta solución, aunque más simple que la mayoría de los suyos, parece hacer lo que yo quiero …

 public static ObservableCollection OrderThoseGroups( ObservableCollection orderThoseGroups) { ObservableCollection temp; temp = new ObservableCollection(orderThoseGroups.OrderBy(p => p)); orderThoseGroups.Clear(); foreach (string j in temp) orderThoseGroups.Add(j); return orderThoseGroups; } 

El argumento de OrderByDescending es una función que devuelve una clave para ordenar con. En tu caso, la clave es la cadena en sí:

 var result = _animals.OrderByDescending(a => a); 

Si quiere ordenar por longitud, por ejemplo, escribirá:

 var result = _animals.OrderByDescending(a => a.Length); 
 _animals.OrderByDescending(a => a.); 

Si los animales serían una lista del objeto Animal, podría usar una propiedad para ordenar la lista.

 public class Animal { public int ID {get; set;} public string Name {get; set;} ... } ObservableCollection animals = ... animals = animals.OrderByDescending(a => a.Name); 

Esta es una ObservableCollection , que se ordena automáticamente cuando se produce un cambio, activa una clasificación solo cuando es necesario y solo activa una sola acción de cambio de la colección de movimientos.

 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 : ObservableCollection { public Func 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() { 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}, "); } } } 

Salida:

 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, 
 myObservableCollection.ToList().Sort((x, y) => x.Property.CompareTo(y.Property)); 
 ///  /// Sorts the collection. ///  /// The type of the elements of the collection. /// The collection to sort. /// The comparison used for sorting. public static void Sort(this ObservableCollection collection, Comparison comparison = null) { var sortableList = new List(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); } } 

Esta solución se basa en la respuesta de Marco . Tuve algunos problemas con su solución y, por lo tanto, la mejoré al llamar a Move si el índice realmente cambió. Esto debería mejorar el rendimiento y también solucionar el problema vinculado.