Суть проблемы в том, что я делал привязку AJAX, но хотел сделать группировку и сортировку.Для этого требовался процесс ручной сортировки, который сначала сортировался по сгруппированному столбцу, а затем по другим отсортированным столбцам.Сетка затем заботится о настройке пользовательского интерфейса группы.Это было немного сложным для меня, потому что мой проект использует NHibernate в качестве ORM с довольно надежным сервисным уровнем, который обрабатывает запросы.В итоге я заставил сетку работать с вспомогательным классом, который выглядит следующим образом:
public static class TelerikGridHelpers
{
public static IEnumerable<AggregateFunctionsGroup> BuildInnerGroup<T, TObject>(IEnumerable<TObject> group, Func<TObject, T> groupSelector, Func<IEnumerable<TObject>, IEnumerable> innerSelector)
{
return group.GroupBy(groupSelector)
.Select(i => new AggregateFunctionsGroup
{
Key = i.Key,
Items = innerSelector(i)
});
}
public static Func<IEnumerable<TObject>, IEnumerable<AggregateFunctionsGroup>> BuildGroup<T, TObject>(Func<TObject, T> groupSelector, Func<IEnumerable<TObject>, IEnumerable<AggregateFunctionsGroup>> selectorBuilder)
{
var tempSelector = selectorBuilder;
return g => g.GroupBy(groupSelector)
.Select(c => new AggregateFunctionsGroup
{
Key = c.Key,
HasSubgroups = true,
Items = tempSelector.Invoke(c).ToList()
});
}
public static IEnumerable<AggregateFunctionsGroup> ApplyGrouping<T>(IQueryable<T> data, IList<GroupDescriptor> groupDescriptors)
{
Func<IEnumerable<T>, IEnumerable<AggregateFunctionsGroup>> selector = null;
foreach (var descriptor in groupDescriptors.Reverse())
{
var tempDescriptor = descriptor;
if (selector == null)
selector = g => BuildInnerGroup(g.Select(p => p), p => p.GetType().GetProperty(tempDescriptor.Member).GetValue(p, null), i => i.ToList());
else
selector = BuildGroup(p => p.GetType().GetProperty(tempDescriptor.Member).GetValue(p, null), selector);
}
return selector != null
? selector.Invoke(data).ToList()
: null;
}
public static List<Order> GenerateOrderList<T>(this T translator, GridCommand command) where T : IPropertyNameTranslator
{
var orders = new List<Order>();
// Step 1 is to add the grouping orders
if (command.GroupDescriptors.Any())
orders.AddRange(from descriptor in command.GroupDescriptors
let sortField = translator.TranslatePropertyToDomainProperty(descriptor.Member)
select descriptor.SortDirection == ListSortDirection.Ascending ? Order.Asc(sortField) : Order.Desc(sortField));
// Then the sorting
if (command.SortDescriptors.Any())
orders.AddRange(from descriptor in command.SortDescriptors.Where(c => !command.GroupDescriptors.Where(g => g.Member == c.Member).Any())
let sortField = translator.TranslatePropertyToDomainProperty(descriptor.Member)
select descriptor.SortDirection == ListSortDirection.Ascending ? Order.Asc(sortField) : Order.Desc(sortField));
return orders;
}
public static List<ViewOrder> GenerateViewOrderList<T>(this T translator, GridCommand command) where T : IPropertyNameTranslator
{
var orders = new List<ViewOrder>();
// Step 1 is to add the grouping orders
if (command.GroupDescriptors.Any())
orders.AddRange(from descriptor in command.GroupDescriptors
let sortField = translator.TranslatePropertyToDomainProperty(descriptor.Member)
select new ViewOrder { PropertyName = sortField, Ascending = descriptor.SortDirection == ListSortDirection.Ascending});
// Then the sorting
if (command.SortDescriptors.Any())
orders.AddRange(from descriptor in command.SortDescriptors.Where(c => !command.GroupDescriptors.Where(g => g.Member == c.Member).Any())
let sortField = translator.TranslatePropertyToDomainProperty(descriptor.Member)
select new ViewOrder { PropertyName = sortField, Ascending = descriptor.SortDirection == ListSortDirection.Ascending });
return orders;
}
}
Обратите внимание, что я использую ViewModels, у которых есть сглаженные имена свойств, поэтому, если у моего доменного объекта есть свойство типа Address
, ViewModel может иметь имя свойства AddressStreet
и AddressCity
.Мой интерфейс IPropertyTranslator
определяет процесс перевода, в котором я могу перейти от имен членов сортировки строк в объекте GridCommand
к тому, что ожидает мой домен.
* * * * * * * * * * * * * * * *} * * * * * * * * * * * * *.Этот метод используется для генерации списка Order
объектов, которые я передаю своему сервисному уровню при получении результатов.ViewOrder
- это служебный класс, который я использую в пользовательском интерфейсе.Мне все еще нужно реорганизовать эти два последних метода, так как они повторяются.
Вот пример того, как я использую этот вспомогательный класс для извлечения GridModel
для сетки:
public GridModel GetAllOrdersGrid(GridCommand command)
{
var svc = DependencyResolver.Current.GetService<IOrderService>();
var propertyTranslator = new OrdersViewModelTranslator();
var orders =
propertyTranslator.GenerateOrderList(command).ToList();
IFutureValue<long> total;
var orders = svc.FindAll(((command.Page - 1) * command.PageSize), command.PageSize, orders, out total);
var mapper = new Mapper<DomainOrder, OrdersViewModel>();
var viewModels = orders.Select(mapper.MapToViewModel);
return command.GroupDescriptors.Any()
? new GridModel
{
Data = TelerikGridHelpers.ApplyGrouping(viewModels.AsQueryable(), command.GroupDescriptors),
Total = Convert.ToInt32(total.Value)
}
: new GridModel { Data = viewModels, Total = Convert.ToInt32(total.Value) };
}
Естьнемного там, это не имеет отношения ко всему вопросу группировки, но это пример из реальной жизни, так что, возможно, это поможет.