Telerik MVC Grid не группируется должным образом - PullRequest
2 голосов
/ 01 июля 2011

Я использую компонент Telerik MVC Grid для рендеринга группируемой сетки, заполненной через ajax.Сетка хорошо работает, сортировка и разбиение по страницам работают, обновление ajax работает, но когда я пытаюсь сделать группировку, рендеринг облажается.Прилагаются экранные шапки сетки до и после группировки.

Определение сетки довольно простое:

<div id="tabAccounts" class="tab_content">
    @(Html.Telerik().Grid<SharedSimpleAccountListViewModel>()
            .Name("AcctGrid")
            .Columns(columns =>
            {
                columns.Bound(x => x.Number)
                    .HeaderHtmlAttributes(new { @style = "text-align: center;" })
                    .HtmlAttributes(new { @style = "text-align: center;" });
                columns.Bound(x => x.ProviderOrganizationFriendlyName)
                    .Title("Provider");
                columns.Bound(x => x.Name)
                    .Title("Account Name");
                columns.Bound(x => x.BillingLocationName)
                    .Title("Location");
            })
            .Groupable()
            .DataBinding(db => db.Ajax().Select("CustomerAccounts", "Customers", new { id = Model.Id }))
            .Pageable(pager => pager.PageSize(50))
            .Sortable()
    )
</div>

Действие контроллера также прямолинейно (я выиграл 'т, так как это просто извлечение из хранилища).Я использую тему по умолчанию Telerik, поэтому пользовательский CSS отсутствует, и я подтвердил, что необходимые скрипты включены в страницу.

При проверке HTML после группировки выясняется, что в нее внесены изменениятаблицы, но это не добавляет элемент строки таблицы для группы.Вот HTML-код, который существует после попытки группировки:

<table cellspacing="0">
    <colgroup>
        <col class="t-group-col">
            <col><col><col><col>
        </colgroup>
    <thead class="t-grid-header">
        <tr>
            <th class="t-group-cell t-header"> </th>
            <th style="text-align: center;" scope="col" class="t-header">
                <a href="/Customers/Details/408?AcctGrid-orderBy=Number-asc" class="t-link">Number</a>
            </th>
            <th scope="col" class="t-header">
                <a href="/Customers/Details/408?AcctGrid-orderBy=ProviderOrganizationFriendlyName-asc" class="t-link">Provider</a>
            </th>
            <th scope="col" class="t-header">
                <a href="/Customers/Details/408?AcctGrid-orderBy=Name-asc" class="t-link">Account Name</a>
            </th>
            <th scope="col" class="t-header t-last-header">
                <a href="/Customers/Details/408?AcctGrid-orderBy=BillingLocationName-asc" class="t-link">Location</a>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td style="text-align: center;">00002</td>
            <td>Acme</td>
            <td>Test account 2 </td>
            <td class="t-last">Location 2</td>
        </tr>
        <tr class="t-alt">
            <td style="text-align: center;">00001</td>
            <td>3M</td>
            <td>Test account 1</td>
            <td class="t-last">Location 1</td>
        </tr>
    </tbody>
</table>

Есть идеи, что здесь происходит?

1 Ответ

3 голосов
/ 09 ноября 2011

Суть проблемы в том, что я делал привязку 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) };
    }

Естьнемного там, это не имеет отношения ко всему вопросу группировки, но это пример из реальной жизни, так что, возможно, это поможет.

...