MvcContrib Grid Сортировка по сложному объекту - PullRequest
4 голосов
/ 05 июля 2011

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

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

Ответы [ 2 ]

3 голосов
/ 05 июля 2011

Проблема здесь на самом деле не связана с сеткой, а скорее с методом расширения .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);
    }
}
1 голос
/ 28 июня 2013

OMG! Dots!

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

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

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

Его код спас меня ...: D Использование функции LINQ Aggregate было УДИВИТЕЛЬНЫМ! Kudozzz ему.

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

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 

Обратите внимание, что при создании столбцов Grid вы можете указать

.SortColumnName("User.UserName")
...