MvcContrib Grid Sorting по сложному объекту

Я пытаюсь работать с MvcContrib сеткой. Но я не могу заставить сортировку работать со сложными объектами, которые содержат другие объекты.

Я установил свой контроллер / классы / представления, аналогичные OP в этом вопросе. Сортировка с помощью 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 не является свойством Issue».

TIA


person SimpleUser    schedule 05.07.2011    source источник


Ответы (2)


Проблема здесь на самом деле не связана с сеткой, а скорее с методом расширения .OrderBy, предоставляемым как часть расширений сортировки MvcContrib. Это расширение довольно упрощено, и я написал его только для простых случаев, когда вы хотите выполнить сортировку по прямому свойству объекта, однако в вашем случае вы пытаетесь упорядочить вложенное свойство ("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);
    }
}
person Jeremy Skinner    schedule 05.07.2011
comment
Спасибо за ответ Джереми. У меня есть целая куча этих вложенных свойств, поэтому в этом случае они могут быть не идеальными. Есть ли шанс, что это скоро будет добавлено в код MvcContrib? - person SimpleUser; 05.07.2011
comment
Лично у меня нет никаких планов добавлять это - я больше не активно работаю над кодовой базой mvccontrib (но если бы кто-то еще захотел внести это, я был бы счастлив объединить его). На самом деле я бы посоветовал сохранять модели представлений как можно более плоскими и не полагаться на сложные графы объектов внутри представлений для простоты. - person Jeremy Skinner; 06.07.2011
comment
Вы можете посмотреть Dynamic.Linq OrderBy. Немного поздно я уверен = P - person Mike Cheel; 07.10.2011

МОЙ БОГ! Точки!

Я был в той же лодке, но, слава богу, я нашел блестящее решение, опубликованное нашим коллегой-разработчиком Джарреттом Мейером. Я нашел его, может быть, через 3 часа поиска в Google в прошлом и только сейчас, когда я решил усилить разбиение на страницы и сортировку с помощью MvcContrib Grid.

Вы можете найти полный текст здесь:

Сортировка на стороне сервера с динамическим LINQ

Его код спас меня ...: D Использование LINQ's Функция агрегирования была УДИВИТЕЛЬНОЙ! Престижность ему.

Мне пришлось немного изменить исходный код Джарретса, чтобы он соответствовал моим потребностям. Вот код после того, как я его изменил:

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")
person Leniel Maccaferri    schedule 28.06.2013