在 ASP.NET 4.5 中使用模型绑定对导航 属性 上的 GridView 进行排序

Sorting a GridView on a navigation property that uses Model Binding in ASP.NET 4.5

模型绑定有很多好处,当您想要将一些数据放入页面上的 gridview 并快速获取并 运行 时,可以节省大量时间。例如,我可以让这个 Employee class

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Job> Jobs { get; set; } 
    [NotMapped]
    public Job CurrentJob
    { 
        get { return Jobs.OrderByDescending(x => x.StartDate).FirstOrDefault(); }
    }

我使用模型绑定将其放入 gridview 中,并使用模板字段计算 属性:

<asp:GridView runat="server" id="gvDataItemType" ItemType="Model.Employee" SelectMethod="Select" AllowSorting="True">
    <Columns>            
        <asp:DynamicField DataField="Name"/>
        <asp:DynamicField DataField="Email"/>    
        <asp:TemplateField HeaderText="Job" SortExpression="???">
            <ItemTemplate>
                <asp:Label ID="lblJobTitle" Text='<%# Bind("CurrentJob.JobName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        ...

在后面的代码中使用以下 Select 方法:

public IQueryable<Employee> Select()
{
    MyContext context = new MyContext();
    return context.Employees;
}    

除 CurrentJob.JobName 属性 之外,一切都很好。

我的问题是: 如何对 CurrentJob.JobName 属性 上的 GridView 进行排序?

我想我可以回答我自己的问题。我在我的模板字段中添加了一个与现有排序表达式不对应的唯一排序表达式:

<asp:TemplateField HeaderText="Job" SortExpression="MeaninglessSortExpression">
            <ItemTemplate>
                <asp:Label runat="server" ID="lblJobTitle" Text='<%# Bind("CurrentJob.Job.JobName") %>'></asp:Label>

然后我发现 gridview 的 SelectMethod 会寻找这样的参数:

Select(string sortByExpression)

然后我只是将一些条件逻辑直接放入我的 select 方法中。甚至不需要处理 OnSorting 或类似的东西:

public IQueryable<Employee> Select(string sortByExpression)
    {
        MyContext context = new MyContext ();
        if (sortByExpression == "MeaninglessSortExpression")
        {                
            return context.Employees.OrderBy(x => x.Jobs.OrderByDescending(y => y.StartDate).FirstOrDefault().Job.JobName);
        }

它有点冗长,但我不能 运行 基于 x => x.CurrentJob 的 LinqQuery,因为它是一个计算 属性。无论如何,这奏效了。我什至不需要手动调用 DataBind();唯一需要注意的是,这显然会覆盖默认的排序功能,因此您可以像这样重现它:

else
{
return context.employees.SortBy(sortByExpression); 

这也很有帮助:ASP.Net 4.5 Model Binding Sorting By Navigation Property

我没有使用 Entity Framework 来检索我的数据,但我使用了像这样的通用比较器解决方案来处理业务对象的排序... http://www.davidgiard.com/2008/06/26/SortingAGridViewBoundToAGenericList.aspx

我调整了 GenericComparer class 的比较方法,以便它可以处理 null 属性,但除此之外,我已经在几个项目中实现了它。