IQueryable порядок по двум или более свойствам
В настоящее время я заказываю список настраиваемых объектов с использованием метода IQueryable OrderBy следующим образом:
mylist.AsQueryable().OrderBy("PropertyName");
Теперь я ищу сортировку более чем одного свойства. Есть ли способ сделать это?
Спасибо,
Яннис
Ответы
Ответ 1
OrderBy(i => i.PropertyName).ThenBy(i => i.AnotherProperty)
В OrderBy и ThenBy вы должны предоставить функцию keySelector, которая выбирает ключ для сортировки с объекта. Поэтому, если вы знаете имя свойства только во время выполнения, вы можете сделать такую функцию с помощью Reflection как:
var propertyInfo = i.GetType().GetProperty("PropertyName");
var sortedList = myList.OrderBy(i => propertyInfo.GetValue(i, null))
Но это будет медленнее, а затем прямой доступ к свойству. Также вы можете "скомпилировать" такую функцию "на лету" с помощью Linq.Expressions, и она будет работать быстрее, чем отражение, но это не очень просто. Или вы можете использовать CollectionViewSource и их функции сортировки в WPF.
И не забывайте, что OrderBy() возвращает отсортированную перечислимую и не сортирует ваш существующий List inplace. В вашем примере вы не сохранили отсортированный список в переменной.
Ответ 2
Вы можете использовать .ThenBy
:
var result = mylist
.AsQueryable()
.OrderBy(x => x.PropertyName)
.ThenBy(x => x.SomeOtherProperty);
Ответ 3
Возможно, вы захотите использовать метод расширения ThenBy, чтобы иметь возможность сортировки по нескольким полям
return myList.AsQueryable().OrderBy(m=>m.Property1).ThenBy(m => m.Property2);
Если вам нужен динамический Linq, посмотрите LinqKit. Недавно я реализовал динамическую библиотеку Microsoft Linq из здесь и смог отсортировать по двум полям, используя строку.
Потрясающие вещи! Не уверен, будет ли это в .NET 5 или нет.
Ответ 4
Как предлагали другие, вы можете использовать "ThenBy". Если вы хотите преобразовать строку в другое значение перед ее использованием, это тоже возможно, например...
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;
});