Trier La Collecte Observable C#

j'ai en dessous de ObservableCollection<string> . Je dois trier 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 faire ?

32
demandé sur slavoo 2013-10-01 13:42:33

9 réponses

Introduction

fondamentalement, s'il y a un besoin d'afficher une collection triée, s'il vous plaît envisager d'utiliser la classe CollectionViewSource : assignez ("bind") sa propriété Source à la collection source - une instance de la classe ObservableCollection<T> .

l'idée est que CollectionViewSource classe fournit une instance de la CollectionView classe . C'est une sorte de "projection" de la collection originale (source), mais avec tri appliqué, filtrage, etc.

, les Références:

"1519320920 Vivre" Façonner

WPF 4.5 introduit la fonction" Live Shaping "pour CollectionViewSource .

, les Références:

Solution

S'il y a encore un besoin de trier une instance de la classe ObservableCollection<T> , voici comment cela peut être fait. La classe ObservableCollection<T> lui-même n'a pas de méthode de tri. Mais, la collection pourrait être recréé pour avoir des articles triés:

// 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));

détails supplémentaires

s'il vous Plaît noter que OrderBy() et OrderByDescending() méthodes (comme d'autres LINQ–les méthodes d'extension) ne pas modifier la source de la collection! Ils créent plutôt une nouvelle séquence (c'est-à-dire une nouvelle instance de la classe qui implémente IEnumerable<T> interface). Ainsi, il est nécessaire pour recréer la collection.

78
répondu Sergey Brunov 2018-08-06 19:27:09

je sais est une vieille question, mais est le premier résultat de google pour "sort observablecollection" donc pensé qu'il vaut la peine de laisser mes deux cents.

Le chemin

la façon dont je vais est de construire un List<> à partir du ObservableCollection<> , le Trier (par sa méthode Sort() , plus sur msdn ) et quand le List<> a été trié, réordonner le ObservableCollection<> avec le Move() méthode.

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]);
    }
}
27
répondu Marco 2016-06-17 12:37:21

j'ai créé une méthode d'extension de la collecte observable

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

Il semble que cela fonctionne et que vous n'avez pas besoin de mettre en œuvre IComparable

5
répondu Lance 2017-04-25 13:57:37

j'ai regardé ceci, j'étais en train de le trier, et puis il a cassé la reliure, comme ci-dessus. J'ai trouvé 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
répondu John Leone 2016-08-19 16:24:25

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

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

si vous voulez Trier par longueur par exemple, vous écrirez:

var result = _animals.OrderByDescending(a => a.Length);
3
répondu manji 2013-10-01 09:58:41
_animals.OrderByDescending(a => a.<what_is_here_?>);

si les animaux seraient une liste D'objet Animal, vous pourriez 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
répondu Bram Van Strydonck 2013-10-01 09:59:21

il s'agit d'un ObservableCollection<T> , qui se trie automatiquement sur un changement, déclenche une sorte seulement si nécessaire, et ne déclenche une seule action de changement de collection mouvement.

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,
3
répondu Shimmy 2017-06-07 01:45:58
myObservableCollection.ToList().Sort((x, y) => x.Property.CompareTo(y.Property));
2
répondu SabariMurugan Sivakumar 2017-06-04 13:21:22
/// <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 l'ai donc améliorée en appelant seulement Move si l'indice a effectivement changé. Cela devrait améliorer les performances et également résoudre la question liée.

1
répondu Tim Pohlmann 2017-05-23 12:34:19