我正在尝试使用MvcContrib
网格控件。但我似乎无法对包含其他对象的复杂对象进行排序。
我在这个问题中设置了类似于OP的控制器/类/视图。 Sorting with MVCContrib
我曾尝试将SortColumnName用于我的childobject.property,但它给出了一个错误,说我的主对象没有此属性。这是我的代码段
// POCO class
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不是Issue的属性'。
TIA
答案 0 :(得分: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);
}
}
答案 1 :(得分:1)
OMG!点!
我在同一条船上,但感谢上帝,我找到了由我们的同事Jarrett Meyer发布的精彩解决方案。我发现它可能是过去3个小时的谷歌搜索,刚才我决定用MvcContrib
网格来提升我的分页和排序。
您可以在此处找到完整的帖子:
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
是位于MvcContrib.UI.Grid
的GridSortOptions。
sort.ColumnName
现在可以包含这些字符串:
User.UserName
User.MyRelatedEntity.RelatedEntityProperty
User.MyRelatedEntity.RelatedEntityProperty.AndSoON
请注意,在创建Grid列时,您可以指定
.SortColumnName("User.UserName")