2011-07-05 74 views
4

我正在嘗試使用MvcContrib網格控件。但我似乎無法使用排序來處理包含其他對象的複雜對象。MvcContrib Grid對複雜對象進行排序

我在這個問題中設置了我的控制器/類/視圖類似於OP。 Sorting with 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不是問題的屬性'。

TIA

回答

3

這裏的問題是實際上沒有涉及到電網,而是作爲MvcContrib排序擴展的一部分提供的.OrderBy擴展方法。這個擴展是相當簡單的,我只寫了它來覆蓋你想要對對象的直接屬性進行排序的簡單情況,但是在你的情況下,你試圖在嵌套屬性(「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); 
    } 
} 
+0

謝謝您的回覆傑里米。我有這些嵌套屬性的全部負載,所以在這種情況下可能不理想。這很快就會被添加到MvcContrib代碼中嗎? – SimpleUser

+0

就我個人而言,我沒有任何計劃添加這個 - 我不再積極地開發mvccontrib代碼庫(但是如果有人想貢獻它,我很樂意合併它)。我實際上建議保持視圖模型儘可能平坦,並且不要依賴視圖中的複雜對象圖形來簡化。 –

+0

您可以查看Dynamic.Linq OrderBy。有點晚了,我確定= P –

1

OMG!點!

我在同一條船上,但感謝上帝,我找到了我們的開發夥伴Jarrett Meyer發佈的精彩解決方案。我在過去3個小時的搜索結果中發現它,剛纔我決定用MvcContrib Grid來提升我的分頁和排序。

你可以在這裏找到完整的信息:

Server-Side Sorting With Dynamic LINQ

他的代碼救了我......:d使用LINQ's Aggregate功能是真棒! Kudozzz給他。

我必須稍微改變Jarretts的原始代碼以適合我的需要。下面的代碼我修改後:

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 

注意,當您創建的網格列你可以指定

.SortColumnName("User.UserName")