2011-07-05 39 views
4

我正在尝试使用MvcContrib网格控件。但我似乎无法使用排序来处理包含其他对象的复杂对象。MvcContrib Grid对复杂对象进行排序

我在这个问题中设置了我的控制器/类/视图类似于OP。 Sorting with MVCContrib

我试图使用SortColumnName到我的childobject.property,但它给了我一个错误,说我的主要对象没有这个属性。这是我的代码片段

// POCO类

class Issue { 
    public int ID {get; get; } 
    ..... 
    public int priorityId {get; set;} 
    public virtual Priority priority {get; set;} 
} 

//控制器代码

public ViewResult Index(int? pageNo, GridSortOptions sort) 
    { 
     var issues = db.issues.Include(i => i.priority); 
     ViewBag.sort = sort; 

     if (!string.IsNullOrEmpty(sort.Column)) 
     { 
      issues = issues.OrderBy(sort.Column, sort.Direction); 
     } 
     return View(issues.ToList().AsPagination(pageNo ?? 1, 10)); 
    } 

//信息查看网格

@Html.Grid(Model).Sort(ViewBag.sort as GridSortOptions).Columns(column => { 
    column.For(issue => Html.ActionLink(" ", "Edit", new { id = issue.ID, areas = "Issues", controller = "Main"}, new { @id="editBtn"})).Named("Edit"); 
    column.For(issue => Html.ActionLink(issue.ID.ToString(), "Edit", new {id = issue.ID, areas = "Issues", controller = "Main"})).Named("ID").Sortable(true); 
    column.For(issue => issue.priority.codeDesc).Named("Priority").SortColumnName("priority.codeDesc").Sortable(true); 
}).Empty("No data found") 

代码当我尝试整理在优先级字符串上,它给了我一个错误,说'priority.codeDesc不是问题的属性'。

TIA

回答

3

这里的问题是实际上没有涉及到电网,而是作为MvcContrib排序扩展的一部分提供的.OrderBy扩展方法。这个扩展是相当简单的,我只写了它来覆盖你想要对对象的直接属性进行排序的简单情况,但是在你的情况下,你试图在嵌套属性(“priority.codeDesc”)上进行排序,不支持 - 你不能在这个扩展名中使用点符号。

你需要切换到使用不同的机制来执行实际的排序,或者如果这是一次性的情况,那么你可以硬编码这个特定列的排序逻辑(不理想,但如果这是一个比那时更容易编写新的排序机制),例如:

if (!string.IsNullOrEmpty(sort.Column)) 
{ 
    if(sort.Column == "priority.codeDesc") 
    { 
     issues = issues.OrderBy(x => x.priority.codeDesc); 
    } 
    else 
    { 
     issues = issues.OrderBy(sort.Column, sort.Direction); 
    } 
} 
+0

谢谢您的回复杰里米。我有这些嵌套属性的全部负载,所以在这种情况下可能不理想。这很快就会被添加到MvcContrib代码中吗? – SimpleUser

+0

就我个人而言,我没有任何计划添加这个 - 我不再积极地开发mvccontrib代码库(但是如果有人想贡献它,我很乐意合并它)。我实际上建议保持视图模型尽可能平坦,并且不要依赖视图中的复杂对象图形来简化。 –

+0

您可以查看Dynamic.Linq OrderBy。有点晚了,我确定= P –

1

OMG!点!

我在同一条船上,但感谢上帝,我找到了我们的开发伙伴Jarrett Meyer发布的精彩解决方案。我在过去3个小时的搜索结果中发现它,刚才我决定用MvcContrib Grid来提升我的分页和排序。

你可以在这里找到完整的信息:

Server-Side Sorting With Dynamic LINQ

他的代码救了我......:d使用LINQ's Aggregate功能是真棒! Kudozzz给他。

我必须稍微改变Jarretts的原始代码以适合我的需要。下面的代码我修改后:

public static IQueryable<T> OrderBy<T>(this IQueryable<T> collection, GridSortOptions sortOptions) 
{ 
    if (string.IsNullOrEmpty(sortOptions.Column)) 
    { 
     return collection; 
    } 

    Type collectionType = typeof(T); 

    ParameterExpression parameterExpression = Expression.Parameter(collectionType, "p"); 

    Expression seedExpression = parameterExpression; 

    Expression aggregateExpression = sortOptions.Column.Split('.').Aggregate(seedExpression, Expression.Property); 

    MemberExpression memberExpression = aggregateExpression as MemberExpression; 

    if (memberExpression == null) 
    { 
     throw new NullReferenceException(string.Format("Unable to cast Member Expression for given path: {0}.", sortOptions.Column)); 
    } 

    LambdaExpression orderByExp = Expression.Lambda(memberExpression, parameterExpression); 

    const string orderBy = "OrderBy"; 

    const string orderByDesc = "OrderByDescending"; 

    Type childPropertyType = ((PropertyInfo)(memberExpression.Member)).PropertyType; 

    string methodToInvoke = sortOptions.Direction == MvcContrib.Sorting.SortDirection.Ascending ? orderBy : orderByDesc; 

    var orderByCall = Expression.Call(typeof(Queryable), methodToInvoke, new[] { collectionType, childPropertyType }, collection.Expression, Expression.Quote(orderByExp)); 

    return collection.Provider.CreateQuery<T>(orderByCall); 
} 

现在你可以这样调用该扩展方法在你的控制器方法:

var users = Database.Memberships.OrderBy(sort); 

其中sort是GridSortOptions生活在MvcContrib.UI.Grid

sort.ColumnName现在可以包含像这些的字符串:

User.UserName 
User.MyRelatedEntity.RelatedEntityProperty 
User.MyRelatedEntity.RelatedEntityProperty.AndSoON 

注意,当您创建的网格列你可以指定

.SortColumnName("User.UserName")