0

Model binding has a lot of benefits and saves a lot of time when you want to throw some data into a gridview on a page and get it up and running quickly. For example, I can have this 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(); }
    }

I throw this into a gridview using Model Binding and a template field for the calculated property:

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

with the following Select Method in code behind:

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

Everything sorts wonderfully except, obviously, the CurrentJob.JobName property.

My question is: How can I sort the GridView on the CurrentJob.JobName property?

Mike
  • 135
  • 2
  • 10

2 Answers2

0

I think I can answer my own question. I added a unique sort expression to my template field that didn't correspond with an existing sort expression:

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

and then I discovered that the gridview's SelectMethod will look for an argument like this:

Select(string sortByExpression)

Then I just threw some conditional logic right into my select method. No need to even deal with the OnSorting or anything like that:

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

It's a little verbose, but I couldn't run a LinqQuery based on x => x.CurrentJob since it's a calculated property. Anyway this worked. I didn't even need to manually call DataBind(); The only caveat is that this apparently overrides the default sort functionality, so you can reproduce it like this:

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

This was also helpful: ASP.Net 4.5 Model Binding Sorting By Navigation Property

Community
  • 1
  • 1
Mike
  • 135
  • 2
  • 10
0

I'm not using Entity Framework to retrieve my data but I've used a generic comparer solution like this to handle sorting on business objects... http://www.davidgiard.com/2008/06/26/SortingAGridViewBoundToAGenericList.aspx

I adjusted the GenericComparer class's Compare method so it can handle null properties but other than that I've implemented this on several projects.

eric1825
  • 405
  • 3
  • 13