4

我有一个关于按多列对列表进行排序的问题。在下面的示例中,即使我排序为 show None, A First Description, B Second...,列表仍然按照插入的顺序打印。

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

可以在不分配的情况下完成订购(如上)吗?

仅供参考,此示例不是实际代码。我需要将这个列表数据绑定到一个ComboBoxinWPF通过代码后面 using 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));

以上在 UI 中完成了技巧。我感谢所有人的快速回答。

4

4 回答 4

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

这只是一个想法,我不知道它是否会起作用,或者它是否是一个好主意。

于 2013-03-22T17:20:33.197 回答
2

Since you have a List, you can do it the old school way:

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

But I'd probably stick with LINQ. Much easier to read.

于 2013-03-22T17:24:49.303 回答
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排序不会改变 - 仅设置特定循环的顺序。

如果这些都不可接受,请更详细地说明您的需求。

于 2013-03-22T17:31:13.847 回答
0

只是作为替代方案,“请不要这样做,除非没有其他适合”路线,您可以添加一个新属性以对合并进行排序:

class NoReallyThisIsACodeSmell
{
    public string SortPlusDescription
    {
           return string.Concat(SortOrder, Description);
    }
}
于 2013-03-22T17:34:14.203 回答