2013-03-22 4 views
3

У меня вопрос по сортировке списка по нескольким столбцам. В следующем примере, хотя я отсортировал, чтобы показать None, A First Description, B Second..., список по-прежнему печатает в том порядке, в котором он был вставлен.Сортировка списка C# несколькими столбцами

List<MySample> samples = new List<MySample>(); 

samples.Add(new MySample { SortOrder = 1, Data = "A First Description", Description = "A First Description" }); 
samples.Add(new MySample { SortOrder = 1, Data = "C Third Description", Description = "C Third Description" }); 
samples.Add(new MySample { SortOrder = 1, Data = "B Second Description", Description = "B Second Description" }); 
samples.Add(new MySample { SortOrder = 0, Data = "None", Description = "None" }); 
samples.OrderBy(a => a.SortOrder).ThenBy(a => a.Description).ToList(); 

foreach (var item in samples) 
{ 
    Console.WriteLine(item); 
} 

public class MySample 
{ 
    public int SortOrder { get; set; } 
    public string Description { get; set; } 
    public object Data { get; set; } 
} 

Если я изменю свой код, чтобы сделать следующее, он печатает в требуемом порядке.

samples = samples.OrderBy(a => a.SortOrder).ThenBy(a => a.Description).ToList(); 

Можно ли заказать заказ без назначения (например, выше)?

FYI, этот пример не является фактическим кодом. Мне нужно привязать этот список к ComboBox в WPF с помощью кода, использующего FrameworkElementFactory.

Спасибо за помощь!

Обновление с моим подходом:

var collectionView = CollectionViewSource.GetDefaultView(<My list to be sorted>); 
collectionView.SortDescriptions.Add(new SortDescription("SortOrder", ListSortDirection.Ascending)); 
collectionView.SortDescriptions.Add(new SortDescription("Description", ListSortDirection.Ascending)); 

выше сделал трюк в пользовательском интерфейсе. Я благодарю всех за быстрые ответы.

+2

'list' обеспечивает' Сгруппировать 'функция, которая не требует назначения, но это сложнее, потому что это связано с написанием собственного Comparer. –

+0

Один основной вопрос. Все ответы были очень полезными. Я не уверен, как правильно выбрать ответ в этом сценарии? – isakavis

ответ

4

Причина в том, что OrderBy не преобразует объект, на который он вызывается, вместо этого он возвращает новый результат. Вы должны использовать его как это:

samples = samples.OrderBy(a => a.SortOrder).ThenBy(a => a.Description).ToList(); 

Это путь функция OrderBy работает. Зачем вам это нужно, чтобы работать по-другому, особенно для нескольких лишних символов.

может заставить работать, создавая собственные методы расширения, которые делают то же самое, кроме работы над ссылкой на объект, а не создают новый результат, но это не стоит проблем.


Если вам нужно что-то, хотя, можно просто обернуть LINQ в метод расширения так:

public static void MyOrderBy(this List<MySample> list) 
{ 
    list = list.OrderBy(a => a.SortOrder).ThenBy(a => a.Description).ToList(); 
} 

и использовать его как так:

samples.MyOrderBy(); 

Это просто идея, хотя, я не знаю, будет ли это работать, или если это хорошая идея или нет.

+0

Спасибо за ваш ответ. В фактическом коде я не могу назначить список с помощью orderby, поскольку он является частью объекта, который мы не можем изменить. Я думаю, если сортировочный компаратор предоставит мне необходимую функциональность (как комментарий Кендалла)? Основная цель - не изменять исходный объект, а сортировать его для отображения, как это требует пользовательский интерфейс. Не уверен, ясно ли я объяснил свое ограничение. Дайте мне знать, если это не ясно. – isakavis

+0

@isakavis: Я сделал редактирование, это просто идея, но, возможно, это поможет вам – musefan

+2

Это не сработает, так как 'list' не является параметром' ref'; то есть вы назначаете новый список только локальной копии в методе 'MyOrderBy'. –

2

Поскольку у вас есть List, вы можете сделать это старый школьный путь:

samples.Sort((s1, s2) => { 
    int compare = s1.SortOrder.CompareTo(s2.SortOrder); 
    if (compare != 0) return compare; 
    compare = s1.Description.CompareTo(s2.Description); 
    return compare; 
}); 

Но я бы, вероятно, придерживаться LINQ. Намного легче читать.

+0

Да. Это имеет преимущество в том, что вы выполняете локальную сортировку и не создаете новый список в качестве подхода LINQ. –

1

Вы можете изменить свой пример:

//other code above... 
samples.Add(new MySample { SortOrder = 0, Data = "None", Description = "None" }); 
foreach (var item in samples.OrderBy(a => a.SortOrder).ThenBy(a => a.Description)) 
//other code below... 

Обратите внимание, что samples неизменна упорядочением - только порядок для этого конкретного проходного установлено.

Если ни один из этих вариантов не является приемлемым, пожалуйста, объясните свою потребность более подробно.

0

Просто для альтернативы «пожалуйста, не делайте этого, если ничего не подходит» маршрут, вы могли добавить новое свойство для сортировки на укрупнение:

class NoReallyThisIsACodeSmell 
{ 
    public string SortPlusDescription 
    { 
      return string.Concat(SortOrder, Description); 
    } 
} 
+0

Я иду по этому маршруту (который, как вы сказали, «не делайте этого»), вы захотите отформатировать это значение SortOrder, чтобы количество цифр было одинаковым, например 'string.Concat (SortOrder. ToString («0000000000»), описание) - ваши значения будут такими, как «0000000123ABC» и «0000000012CDE». –

+1

@JoeEnos Хорошая точка - у меня есть ограничения на терпение при отправке ответов с моего телефона :) – JerKimball