ASP.Net 4.5模型绑定排序通过导航属性 [英] ASP.Net 4.5 Model Binding Sorting By Navigation Property

查看:293
本文介绍了ASP.Net 4.5模型绑定排序通过导航属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所有,

我有以下几列网格视图。分页工作的伟大,但不排序。每次我在分类列中单击按类别进行排序我会得到这个错误:

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

此错误说法是不正确的,因为GridView控件能够正确显示列。

下面是选择方法

 公开的IQueryable<项目> getProjects()
    {
        ApplicationServices objServices =新ApplicationServices();
        IQueryable的<项目> lstProject;
        lstProject = objServices.getProjects();
        返回lstProject;
    }

任何建议?

 < ASP:GridView控件ID =grdProject=服务器ShowHeader =真
        的AutoGenerateColumns =假CELLPADDING =2CELLSPACING =2
        而itemtype =ESA.Data.Models.Entity.Project
        SelectMethod =getProjects
        的DataKeyNames =专案编号
        AllowSorting =真
        AllowPaging =真
        每页=5>
        <柱体和GT;
            < ASP:BoundField的数据字段=专案编号的HeaderText =IDItemStyle-WIDTH =10/>
            < ASP:BoundField的数据字段=Category.CategoryName的HeaderText =类别SORTEX pression =Category.CategoryName/>
            < ASP:BoundField的数据字段=项目名的HeaderText =项目名称ItemStyle-WIDTH =300/>
            < ASP:BoundField的数据字段=Status.StatusName的HeaderText =状态SORTEX pression =Status.StatusName/>
            < ASP:BoundField的数据字段=AddedByUser.UserName的HeaderText =添加者ItemStyle-WIDTH =120/>
            < ASP:BoundField的数据字段=AddedDate的HeaderText =添加日期ItemStyle-WIDTH =90DataFormatString ={0:D}/>
        < /专栏>
    < / ASP:GridView的>


解决方案

我是有ListView控件类似的问题。
我解决了这个样子。

首先我用code,从这个职位由Marc Gravell 动态LINQ排序依据

在我的ListView的OnSorting事件添加以下code。

 保护无效lv_Sorting(对象发件人,ListViewSortEventArgs E)
{
    e.Cancel =真;
    的ViewState [排序依据] = e.SortEx pression;
    lvList.DataBind();
}

我添加了一个相当标准的方式来捕捉sortdirection榜单

 公共SortDirection sortDirection
{
    得到
    {
        如果(的ViewState [sortdirection] == NULL)
        {
            的ViewState [sortdirection] = SortDirection.Ascending;
            返回SortDirection.Ascending;
        }
        否则,如果((SortDirection)的ViewState [sortdirection] == SortDirection.Ascending)
        {
            的ViewState [sortdirection] = SortDirection.Descending;
            返回SortDirection.Descending;
        }
        其他
        {
            的ViewState [sortdirection] = SortDirection.Ascending;
            返回SortDirection.Ascending;
        }
    }
    组
    {
        的ViewState [sortdirection] =值;
    }
}

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

 公开的IQueryable< SomeObject> GetObjects([视图状态(排序依据)]字符串的OrderBy = NULL)
{
    VAR列表= GETSOMEOBJECTS();
    如果(排序依据!= NULL)
    {
        开关(sortDirection)
        {
            案例SortDirection.Ascending:
                清单= list.OrderByDescending(排序依据);
                打破;
            案例SortDirection.Descending:
                清单= list.OrderBy(排序依据);
                打破;
            默认:
                清单= list.OrderByDescending(排序依据);
                打破;
        }
    }
    返回列表;
}

我还没有一个GridView尝试过,但我敢肯定它会工作一样。

修改
下面是应该工作的LINQ扩展类的例子

 公共静态类LinqExtensions
{
    公共静态IOrderedQueryable< T>排序依据< T>(这IQueryable的< T>源,字符串属性)
    {
        返回ApplyOrder< T>(来源财产排序依据);
    }
    公共静态IOrderedQueryable< T> OrderByDescending< T>(这IQueryable的< T>源,字符串属性)
    {
        返回ApplyOrder< T>(来源财产OrderByDescending);
    }
    公共静态IOrderedQueryable< T> ThenBy< T>(这IOrderedQueryable< T>源,字符串属性)
    {
        返回ApplyOrder< T>(来源财产ThenBy);
    }
    公共静态IOrderedQueryable< T> ThenByDescending< T>(这IOrderedQueryable< T>源,字符串属性)
    {
        返回ApplyOrder< T>(来源财产ThenByDescending);
    }
    静态IOrderedQueryable< T> ApplyOrder< T>(IQueryable的< T>源,字符串属性,字符串methodName中)
    {
        字符串[] =道具property.Split('。');
        类型type = typeof运算(T);
        ParameterEx pression精氨酸=实施例pression.Parameter(类型,×);
        防爆pression EXPR = ARG;
        的foreach(在道具串道具)
        {
            //使用反射(不ComponentModel),以反映LINQ
            PI的PropertyInfo = type.GetProperty(丙);
            EXPR =前pression.Property(表达式,PI);
            键入= pi.PropertyType;
        }
        键入delegateType = typeof运算(Func键<,>)MakeGenericType(typeof运算(T),类型)。
        LambdaEx pression波长=前pression.Lambda(delegateType,EXPR,ARG);        对象result = typeof运算(可查询).GetMethods()。单(
                方法= GT; method.Name ==方法名
                        &功放;&安培; method.IsGenericMethodDefinition
                        &功放;&安培; method.GetGenericArguments()==长度2
                        &功放;&安培; method.GetParameters()。持续== 2)
                .MakeGenericMethod(typeof运算(T),类型)
                .Invoke(空,新的对象[] {源,拉姆达});
        返回(IOrderedQueryable< T>)的结果;
    }
}

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

All,

I have a grid view that has the following columns. The paging work great, but not sorting. Everytime I click on the Category column to sort by category I would get this error:

Instance property 'Category.CategoryName' is not defined for type 'ESA.Data.Models.Entity.Project'

This error statement is not true because the gridview was able to display the column correctly.

Here is the select method

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

Any suggestion?

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

解决方案

I was having a similar issue with a Listview control. I solved it like this.

firstly I'm using the code from this post by Marc Gravell Dynamic LINQ OrderBy

in my Listview's 'OnSorting' event I added the following code.

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

I added a fairly standard way to capture the sortdirection list this

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

In my Listview the Selectmethod looks like this (using the extension method from Marc)

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

I Haven't tried it with a GridView but I'm fairly certain it would work just the same.

EDIT Here is an example of the linq extension class that should work

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

Simply add a using 'whatevernamespaceyouused' to the page and you should be good to go.

这篇关于ASP.Net 4.5模型绑定排序通过导航属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆