2013-05-14 71 views
4

全部,ASP.Net 4.5模型绑定通过导航排序属性

我有一个网格视图,它具有以下列。分页工作很好,但没有排序。每次我点击类别列按类别进行排序,我会得到这个错误:

Instance属性“Category.CategoryName”没有为类型定义“ESA.Data.Models.Entity.Project”

此错误语句不正确,因为gridview能够正确显示列。

这里是选择方法

public IQueryable<Project> getProjects() 
    { 
     ApplicationServices objServices = new ApplicationServices(); 
     IQueryable<Project> lstProject; 
     lstProject = objServices.getProjects(); 
     return lstProject; 
    } 

什么建议吗?

<asp:GridView ID="grdProject" runat="server" ShowHeader="true" 
     AutoGenerateColumns="false" CellPadding="2" CellSpacing="2" 
     ItemType="ESA.Data.Models.Entity.Project" 
     SelectMethod="getProjects" 
     DataKeyNames="ProjectID" 
     AllowSorting="true" 
     AllowPaging="true" 
     PageSize="5"> 
     <Columns> 
      <asp:BoundField DataField="ProjectID" HeaderText="ID " ItemStyle-Width="10" /> 
      <asp:BoundField DataField="Category.CategoryName" HeaderText="Category" SortExpression="Category.CategoryName" /> 
      <asp:BoundField DataField="ProjectName" HeaderText="Project Name" ItemStyle-Width="300" /> 
      <asp:BoundField DataField="Status.StatusName" HeaderText="Status" SortExpression="Status.StatusName" /> 
      <asp:BoundField DataField="AddedByUser.UserName" HeaderText="Added By" ItemStyle-Width="120" /> 
      <asp:BoundField DataField="AddedDate" HeaderText="Added Date" ItemStyle-Width="90" DataFormatString="{0:d}" /> 
     </Columns> 
    </asp:GridView> 
+0

你能粘贴您从控制器发送数据的代码。 – 2013-05-14 18:31:13

+0

我建议看看这里,你可能需要添加一个'asp:LinqDataSource'标签:http://forums.asp.net/t/1213261.aspx/1 – 2013-05-14 18:33:23

+0

Ismet这不是ASP.NET MVC。它是ASP.Net Webform 4.5,我试图使用ASP.NET 4.5提供的新模型绑定功能。 – dnguyen77 2013-05-14 18:48:05

回答

4

我和Listview控件有类似的问题。 我是这样解决的。

首先,我正在使用的代码从这个职位由Marc Gravell Dynamic LINQ OrderBy on IEnumerable<T>

在我的ListView的“OnSorting”事件添加以下代码。

protected void lv_Sorting(object sender, ListViewSortEventArgs e) 
{ 
    e.Cancel = true; 
    ViewState["OrderBy"] = e.SortExpression; 
    lvList.DataBind(); 
} 

我加了一个相当标准的方式来捕捉sortdirection列表此

public SortDirection sortDirection 
{ 
    get 
    { 
     if (ViewState["sortdirection"] == null) 
     { 
      ViewState["sortdirection"] = SortDirection.Ascending; 
      return SortDirection.Ascending; 
     } 
     else if ((SortDirection)ViewState["sortdirection"] == SortDirection.Ascending) 
     { 
      ViewState["sortdirection"] = SortDirection.Descending; 
      return SortDirection.Descending; 
     } 
     else 
     { 
      ViewState["sortdirection"] = SortDirection.Ascending; 
      return SortDirection.Ascending; 
     } 
    } 
    set 
    { 
     ViewState["sortdirection"] = value; 
    } 
} 

在我的ListView中Selectmethod看起来像这样(使用马克扩展方法)

public IQueryable<SomeObject> GetObjects([ViewState("OrderBy")]String OrderBy = null) 
{ 
    var list = GETSOMEOBJECTS(); 
    if (OrderBy != null) 
    { 
     switch (sortDirection) 
     { 
      case SortDirection.Ascending: 
       list = list.OrderByDescending(OrderBy); 
       break; 
      case SortDirection.Descending: 
       list = list.OrderBy(OrderBy); 
       break; 
      default: 
       list = list.OrderByDescending(OrderBy); 
       break; 
     } 
    } 
    return list; 
} 

我没有尝试过用GridView,但我相当肯定它的工作原理是一样的。

编辑 这里是LINQ扩展类的例子,应该工作

public static class LinqExtensions 
{ 
    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property) 
    { 
     return ApplyOrder<T>(source, property, "OrderBy"); 
    } 
    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property) 
    { 
     return ApplyOrder<T>(source, property, "OrderByDescending"); 
    } 
    public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property) 
    { 
     return ApplyOrder<T>(source, property, "ThenBy"); 
    } 
    public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property) 
    { 
     return ApplyOrder<T>(source, property, "ThenByDescending"); 
    } 
    static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName) 
    { 
     string[] props = property.Split('.'); 
     Type type = typeof(T); 
     ParameterExpression arg = Expression.Parameter(type, "x"); 
     Expression expr = arg; 
     foreach (string prop in props) 
     { 
      // use reflection (not ComponentModel) to mirror LINQ 
      PropertyInfo pi = type.GetProperty(prop); 
      expr = Expression.Property(expr, pi); 
      type = pi.PropertyType; 
     } 
     Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type); 
     LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg); 

     object result = typeof(Queryable).GetMethods().Single(
       method => method.Name == methodName 
         && method.IsGenericMethodDefinition 
         && method.GetGenericArguments().Length == 2 
         && method.GetParameters().Length == 2) 
       .MakeGenericMethod(typeof(T), type) 
       .Invoke(null, new object[] { source, lambda }); 
     return (IOrderedQueryable<T>)result; 
    } 
} 

只需添加一个使用“whatevernamespaceyouused”页面,你应该是好去。

+0

非常感谢你的帮助。我正在搜索几天的解决方案,最后你帮我解决了它。 – dnguyen77 2013-05-15 20:55:11

+0

通过设置'e.Cancel = true;'可以禁用GridView排序逻辑,因此您没有“排序”状态的特定样式,例如'SortedAscendingCellStyle'或'SortedAscendingHeaderStyle'。而且,“排序方向”逻辑与gridView并不完全相同。尽管如此,该解决方案仍然有效 – JYL 2014-08-03 09:21:43

+0

我添加了[答案](http://stackoverflow.com/a/25170208/218873),它与gridView逻辑和样式兼容。 – JYL 2014-08-06 21:09:36

0

Drauka您的解决方案对我的作品,但我会得到一个错误在这行代码eventhough我已经引用System.Linq.Dynamic

两行给我的语法错误是

lstProject = lstProject.OrderByDescending(排序依据);

和误差的messge是

的类型参数方法“System.Linq.Enumerable.OrderByDescending(System.Collections.Generic.IEnumerable,System.Func)”不能从使用推断。尝试明确指定类型参数。

public IQueryable<Project> getProjects([ViewState("OrderBy")]String OrderBy = null) 
    { 
     ApplicationServices objServices = new ApplicationServices(); 
     var lstProject = objServices.getProjects(); 
     if (OrderBy != null) 
     { 
      switch (sortDirection) 
      { 
       case SortDirection.Ascending: 
        lstProject = lstProject.OrderByDescending(OrderBy); 
        break; 
       case SortDirection.Descending: 
        lstProject = lstProject.OrderBy(OrderBy); 
        break; 
       default: 
        lstProject = lstProject.OrderByDescending(OrderBy); 
        break; 
      } 
     } 
     return lstProject; 

    } 
+0

您需要使用我通过@marc gravell链接到的扩展方法 – Drauka 2013-05-15 20:19:29

+0

@ dnguyenn77查看更新的回答 – Drauka 2013-05-15 20:27:27

2

将一个名为sortByExpression的字符串参数添加到您的getProjects()方法中。

如果gridView在你的方法签名中找到这个参数,它不会尝试“自动排序”你的结果,它会让你做这项工作。

自己做的工作,你可以使用DynamicLinq(你可以添加nuget package,或使用posted by DraukaLinqExtensions类)。

所以你的方法是这样的:

// using System.Linq.Dynamic; 

public IQueryable<Project> getProjects(string sortByExpression) 
{ 
    ApplicationServices objServices = new ApplicationServices(); 
    IQueryable<Project> lstProject = objServices.getProjects(); 
    if (!String.IsNullOrEmpty(sortByExpression)) 
     lstProject = lstProject.OrderBy(sortByExpression); 
    return lstProject; 
} 

这样,您就不能绕过GridView的排序方式。

来源:反编译代码框架,专门System.Web.UI.WebControls.ModelDataSourceView.IsAutoSortingRequired(...)

+0

您确定这适用于导航属性吗? – Drauka 2014-08-08 11:14:27

+0

@Drauka是的,我用这个为我自己的网站(Asp.net 4.5,EF5)。该解决方案使用与您相同的“OrderBy”方法。 – JYL 2014-08-08 14:16:51