我如何根据用户输入在LINQ中使用OrderBy和ThenBy?

时间:2012-08-27 06:16:01

标签: c# linq

我在页面上有一个网格,我希望可以在多个列上同时对其进行排序。

例如:

UserID        FirstName        LastName
=======================================
1             Bruce            Wayne
2             Peter            Parker
3             Clark            Kent
4             Tony             Stark
5             Helena           Wayne

用户可以选择按LastName ASC排序,然后按FirstName DESC排序,这将生成以下内容:

UserID        FirstName        LastName
=======================================
3             Clark            Kent
2             Peter            Parker
4             Tony             Stark
5             Helena           Wayne
1             Bruce            Wayne

用户可以重置订购并决定以其他方式订购。

如何在LINQ中实现这一目标?据我所知,链排序的方法是做类似

的事情
superheroes.OrderBy(x => x.LastName).ThenByDescending(x => x.FirstName)

显然,我不想写出每个可能的列顺序组合(我的网格最多可能有10列)。有没有办法让订购序列动态化?

3 个答案:

答案 0 :(得分:3)

IEnumerable的一种天真的方法(不完美或测试,但你明白了)。我把开关放在外面,所以比较只进行一次,而不是每次调用选择器。有点难看,因为你基本上不得不在OrderBy和ThenBy中重复自己。

enum OrderableColumns {UserID, FirstName, ...}

IOrderedEnumerable<SuperHero> OrderBy(SuperHeroes superheroes, OrderableColumns column)
{
    switch(column)
    {
        case UserID:
            return superheroes.OrderBy(x => x.UserID);
        case FirstName:
            return superheroes.OrderBy(x => x.FirstName);
        ...
    }
}

IOrderedEnumerable<SuperHero> ThenBy(IOrderedEnumerable<SuperHero> superheroes, OrderableColumns column)
{
    switch(column)
    {
        case UserID:
            return superheroes.ThenBy(x => x.UserID);
        case FirstName:
            return superheroes.ThenBy(x => x.FirstName);
        ...
    }
}

IOrderedEnumerable<SuperHero> OrderSuperheroes(SuperHeroes superheroes, params OrderableColumns[] columns)
{
     var ordered = OrderBy(superheroes, columns[0]);

     foreach(var col in columns.Skip(1))
         ordered = ThenBy(ordered, col);

     return ordered;
}

答案 1 :(得分:2)

答案 2 :(得分:0)

您可以构建Func<T,TResult>动态,如下所示:

public static Func<T,object> GetExp<T>(string preportyName)
{
    var instance = Expression.Parameter(typeof(T));
    var callPreporty = Expression.PropertyOrField(instance, preportyName);
    var lambda = Expression.Lambda<Func<T, object>>(callPreporty,instance);
    return lambda.Compile();
}

像这样使用:

var pdotName = GetExp<Person>("Name");  //equals: p=>p.Name
var pdotID = GetExp<Person>("Id");  ////equals: p=>p.Id
var ordered = list.OrderBy(pdotName).ThenBy(pdotID);
//equals: list.OrderBy(p=>p.Name).ThenBy(p=>p.Id)