2011-06-30 53 views
2

我正在使用Telerik MVC Grid組件來呈現通過ajax填充的可組網網格。網格渲染罰款,排序和分頁工作,阿賈克斯刷新工程,但是當我嘗試分組,渲染得到所有搞砸了。附加的是網格前後分組的屏幕截圖。Telerik MVC Grid未正確分組

電網的定義是相當直接:

<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> 

任何想法可能會發生什麼?

+0

哪裏有屏幕 – Tassadaque

+0

糟糕......是的,我交叉發佈到Telerik,並沒有擦洗之前,我複製。我已經想出了我必須先組織它的解決方案,然後才能將它發佈到SO上。 –

+0

@Jush,Ahem ..你有解決方案嗎?我很想看到它。 – Levitikon

回答

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; 
    } 

} 

請注意,我使用的是具有平坦的屬性名稱的ViewModels,所以如果我的域對象有Address類型的屬性時, ViewModel可能具有屬性名稱AddressStreetAddressCity。我的IPropertyTranslator接口指定了一個轉換過程,我可以從GridCommand對象中的字符串排序成員名稱轉到我的域需求。

倒數第二種方法中的Order類是NHibernate Order。此方法用於生成我檢索結果時傳遞給服務層的對象列表OrderViewOrder是我在UI中使用的實用工具類。我仍然需要重構最後兩種方法,因爲它們是重複的。

這裏是我如何使用這些輔助類來拉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) }; 
    } 

有一個位在那裏,是不相關的分組的全部問題,但它是一個現實世界的例子,所以也許它會有所幫助。

+0

好東西!真的幫助了我 –