web-dev-qa-db-fra.com

Triez ObservableCollection <string> par C #

J'ai ci-dessous ObservableCollection<string>. J'ai besoin de trier ceci par ordre alphabétique.

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"
};

J'ai essayé _animals.OrderByDescending. Mais je ne sais pas comment l'utiliser correctement.

_animals.OrderByDescending(a => a.<what_is_here_?>);

Comment puis-je faire ceci?

35
Bishan

Je sais que c’est une vieille question, mais c’est le premier résultat de Google pour "sort observablecollection", alors j’ai pensé que cela valait la peine de laisser mes deux cents.

Le chemin

Pour ce faire, construisez un List<> à partir du ObservableCollection<>, triez-le (via sa méthode Sort(), more sur msdn ) et, lorsque le List<> est trié, réorganisez le ObservableCollection<> avec la méthode Move().

Le 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);
    }
}

Le 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 element have been sorted
    for (int i = 0; i < maxValue; i++)
    {
        Assert.AreEqual(i, observableCollection[i]);
    }
}
28
Marco

J'ai créé une méthode d'extension à 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);
        }
    }

Cela semble fonctionner et vous n'avez pas besoin de mettre en œuvre IComparable

6
Lance

J'ai regardé ceux-ci, je faisais le tri, puis ça a cassé la reliure, comme ci-dessus. Venu avec cette solution, bien que plus simple que la plupart des vôtres, il semble faire ce que je veux ,

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;



    }
4
John Leone

Il s'agit d'un ObservableCollection<T> qui se trie automatiquement à la suite d'une modification, déclenche un tri uniquement lorsque cela est nécessaire et ne déclenche qu'une seule action de modification de collection de déplacements.

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}, ");
    }
  }
}

Sortie:

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,
4
Shimmy

L'argument de OrderByDescending est une fonction renvoyant une clé avec laquelle trier. Dans votre cas, la clé est la chaîne elle-même:

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

Si vous vouliez trier par longueur par exemple, vous écrirez:

var result = _animals.OrderByDescending(a => a.Length);
3
manji
_animals.OrderByDescending(a => a.<what_is_here_?>);

Si animaux est une liste d'objets Animal, vous pouvez utiliser une propriété pour commander la liste.

public class Animal
{
    public int ID {get; set;}
    public string Name {get; set;}
    ...
}

ObservableCollection<Animal> animals = ...
animals = animals.OrderByDescending(a => a.Name);
3
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);
    }
}

Cette solution est basée sur La réponse de Marco . J'ai eu quelques problèmes avec sa solution et donc l'a améliorée en appelant seulement Move si l'index a réellement changé Cela devrait améliorer les performances et résoudre le problème lié.

1
Tim Pohlmann

J'ai fait une sorte sur un certain champ de classe (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);
        }
0
Kairat Koibagarov