web-dev-qa-db-fra.com

Ordre iQueryable par deux ou plusieurs propriétés

Je commande actuellement une liste d'objets personnalisés à l'aide de la méthode IQueryable OrderBy comme suit:

mylist.AsQueryable().OrderBy("PropertyName");

Maintenant, je cherche à trier par plus d'une propriété. Y'a-t'il un quelconque moyen d'y arriver?

Merci, Yannis

27
Yannis
OrderBy(i => i.PropertyName).ThenBy(i => i.AnotherProperty)

Dans OrderBy et ThenBy, vous devez fournir la fonction keySelector, qui choisit la clé pour le tri à partir de l'objet. Donc, si vous ne connaissez le nom de la propriété qu'au moment de l'exécution, vous pouvez créer une telle fonction avec Reflection comme:

var propertyInfo = i.GetType().GetProperty("PropertyName"); 
var sortedList = myList.OrderBy(i => propertyInfo.GetValue(i, null)) 

Mais ce sera un accès plus lent, puis direct à la propriété. Vous pouvez également "compiler" une telle fonction à la volée avec Linq.Expressions et cela fonctionnera plus rapidement que la réflexion mais ce n'est pas très facile. Ou vous pouvez utiliser CollectionViewSource et leurs capacités de tri dans WPF.

Et n'oubliez pas que OrderBy () renvoie un tri énumérable et ne trie pas votre liste existante en place. Dans votre exemple, vous n'avez pas enregistré la liste triée dans une variable.

52
Nikolay

Vous pouvez utiliser .ThenBy:

var result = mylist
    .AsQueryable()
    .OrderBy(x => x.PropertyName)
    .ThenBy(x => x.SomeOtherProperty);
13
Darin Dimitrov

Vous voudrez probablement utiliser la méthode d'extension ThenBy pour pouvoir trier par plusieurs champs

 return myList.AsQueryable().OrderBy(m=>m.Property1).ThenBy(m => m.Property2);

Si vous voulez Linq dynamique, regardez LinqKit . J'ai récemment implémenté la bibliothèque dynamique Linq de Microsoft à partir de ici et j'ai pu trier par deux champs à l'aide d'une chaîne.

Des trucs géniaux! Je ne sais pas si ce sera dans .NET 5 ou non.

6
Chris Gessler

Comme d'autres l'ont suggéré, vous pouvez utiliser "ThenBy". Si vous souhaitez convertir une chaîne en une valeur différente avant de l'utiliser, cela est également possible, par exemple ...

    var sortedSystemTestResultsList = systemTestResultsList.OrderBy(s =>
    {
        DateTime dt;
        if (!DateTime.TryParse(s.testPointCompletedDate, out dt)) return DateTime.MaxValue;
        return dt;
    }).ThenBy(s =>
    {
        Int32 tpID;
        if (!Int32.TryParse(s.testRunResultID, out tpID)) return Int32.MaxValue;
        return tpID;
    });
0
ZenoArrow