1

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

例如:

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 列)。有什么方法可以使排序顺序动态化吗?

4

3 回答 3

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;
}
于 2012-08-27T06:30:58.193 回答
2

您需要使用动态 LINQ。查看动态 LINQ(第 1 部分:使用 LINQ 动态查询库)

于 2012-08-27T06:20:32.200 回答
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)
于 2012-08-27T07:04:41.313 回答