SPGridView Filter Fields in the wrong Order

SPGridView Filter Fields in the wrong Order

this post is a little throwback.

SPGridView was one of the most useful controls in the classic SharePoint stack. It looked and behaved like a SharePoint list view and gave us powerful table behavior with relatively little code.

In modern SharePoint Online, this exact model is not what we build with anymore. Still, I want to preserve this knowledge so it stays searchable and reusable when we need historical context, migrations, or legacy maintenance.

Why I wrote this (I was asked)

I was asked why filter in an SPGridView looked broken, shifted, or attached to the wrong column.

In most cases, the issue was not in sorting logic itself. The real issue was FilterDataFields order.

Goal

In this post, I document the baseline setup for:

  • Paging
  • Sorting
  • Filtering

1) Prepare a list and a Visual WebPart

  1. Create a list with columns such as:
    • Title
    • Metadata
    • Location
    • FromDateTime
    • ToDateTime
  2. Add a Visual WebPart to your project.
  3. Place an SPGridView inside the WebPart.

2) Initialize ObjectDataSource in page load

In page load, create the data source and then bind the grid:

const string DATASOURCEID = "gridDS";

gridDS = new ObjectDataSource();

gridDS.ID = DATASOURCEID;

gridDS.SelectMethod = "SelectData";

gridDS.TypeName = this.GetType().AssemblyQualifiedName;

gridDS.ObjectCreating += new ObjectDataSourceObjectEventHandler(gvCRBooked_ObjectCreating);

this.Controls.Add(gridDS);

BindGrid();

3) Bind the grid and enable features

Enable paging, sorting, and filtering in one place:

private void BindGrid()

{

    gvCRBooked.AllowPaging = true; 

    // Sorting           

    gvCRBooked.AllowSorting = true; 

    //allow Filtering            

    gvCRBooked.FilterDataFields = "Title,Metadata,Location,FromDateTime,ToDateTime";

    gvCRBooked.FilteredDataSourcePropertyName = "FilterExpression";

    gvCRBooked.FilteredDataSourcePropertyFormat = "{1} = '{0}'";

    gvCRBooked.Sorting += new GridViewSortEventHandler(gvCRBooked_Sorting);

    gvCRBooked.PageIndexChanging += new GridViewPageEventHandler(gvCRBooked_PageIndexChanging);

    //For Filtering

    gridDS.Filtering += new ObjectDataSourceFilteringEventHandler(gvCRBooked_Filtering);

    gvCRBooked.AutoGenerateColumns = false;

    gvCRBooked.AllowFiltering = true;

    gvCRBooked.PagerTemplate = null;

    gvCRBooked.PageSize = 10;

    gvCRBooked.DataSourceID = gridDS.ID;

    gvCRBooked.DataBind();

}

4) Implement pagination

void gvCRBooked_PageIndexChanging(object sender, GridViewPageEventArgs e)

{

    gvCRBooked.PageIndex = e.NewPageIndex;

    gvCRBooked.DataSourceID = gridDS.ID;

    gvCRBooked.DataBind();

}

5) Implement sorting

void gvCRBooked_Sorting(object sender, GridViewSortEventArgs e) 

{     
     string lastExpression = "";   

     if (ViewState["SortExpression"] != null) 

            lastExpression = ViewState["SortExpression"].ToString();

            string lastDirection = "asc";       

     if (ViewState["SortDirection"] != null)         

            lastDirection = ViewState["SortDirection"].ToString();

            string newDirection = string.Empty;          

    if (e.SortExpression == lastExpression)           

    {          

        e.SortDirection = (lastDirection == "asc") ? System.Web.UI.WebControls.SortDirection.Descending : System.Web.UI.WebControls.SortDirection.Ascending; 

    }       newDirection = (e.SortDirection == System.Web.UI.WebControls.SortDirection.Descending) ? "desc" : "asc";  

            ViewState["SortExpression"] = e.SortExpression;           

            ViewState["SortDirection"] = newDirection;

            gvCRBooked.DataBind();             //For Filter  

   if (ViewState["FilterExpression"] != null)           

   {             

      gridDS.FilterExpression = (string)ViewState["FilterExpression"]; 

   }    

}

6) Implement filtering

private void gvCRBooked_Filtering(object sender, ObjectDataSourceFilteringEventArgs e)

{         

    ViewState["FilterExpression"] = ((ObjectDataSourceView)sender).FilterExpression; 

}

Filter not correct or on the wrong position? Check FilterDataFields order

SPGridView uses DataSourceID to locate the ObjectDataSource. After that, it sets the property defined in FilteredDataSourcePropertyName (here: FilterExpression).

FilterDataFields is a little bit tricky:

  • Keep it in exactly the same order as your displayed fields.
  • If you have a column without a filter, you must still keep its position with an empty value.
  • If order is wrong, Filter can look incorrect or appear on the wrong column.

Use this pattern when a column has no filter:

"Title,,Location,FromDateTime,ToDateTime";

TL;DR

  • This is a classic/legacy SharePoint pattern, preserved on purpose.
  • Initialize and register ObjectDataSource correctly.
  • Enable AllowPaging, AllowSorting, and AllowFiltering on the grid.
  • Keep sort/filter state in ViewState.
  • Ensure FilterDataFields order matches your columns.