Telerik MVC Grid没有正确分组

时间:2011-06-30 20:27:46

标签: asp.net-mvc asp.net-mvc-3 telerik-mvc

我正在使用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 个答案:

答案 0 :(得分:3)

问题的关键在于我正在进行AJAX绑定但是想要进行分组和排序。需要的是手动排序过程,首先按分组列排序,然后排序其他排序列。然后网格负责设置组UI。这对我来说是一个挑战,因为我的项目使用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;
    }

}

请注意,我使用的是具有展平属性名称的ViewModel,因此如果我的域对象具有类型为Address的属性,则ViewModel的属性名称可能为AddressStreet和{{1} }。我的AddressCity接口指定了一个转换过程,我可以从IPropertyTranslator对象中的字符串排序成员名称转到我的域期望的名称。

倒数第二个方法中的GridCommand类是NHibernate Order。此方法用于生成我检索结果时传递给服务层的Order个对象列表。 Order是我在UI中使用的实用程序类。我仍然需要重构最后两种方法,因为它们是重复的。

以下是我如何使用该帮助程序类来为网格提取ViewOrder的示例:

GridModel

那里有一点与分组的整个问题无关,但这是一个真实世界的例子,所以也许它会有所帮助。