1. the aspx code

<asp:GridView id="gv" runat="server" OnRowEditing="gv_RowEditing" OnPageIndexChanging="gv_PageIndexChanging" OnSorting="gv_Sorting" >

2. the code behind

public String gvSortDirection
{
  get { return ViewState["SortDirection"] as String ?? "ASC"; }
  set { ViewState["SortDirection"] = value; }
}
public String gvSortExpression
{
  get { return ViewState["SortExpression"] as String ?? ""; }
  set { ViewState["SortExpression"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
  DataTable dataTable = new DataTable();

  // fill datatable with data
  gv.DataSource = GetSortedData(datatable, gvSortExpression, gvSortDirection);
  gv.DataBind();
}
protected void gvUsers_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
  GridView gv = (GridView)sender;
  DataView dv = gv.DataSource as DataView;
  DataTable dataTable = dv.Table;

  gv.DataSource = GetSortedData(dataTable, gvSortExpression, gvSortDirection);
  gv.PageIndex = e.NewPageIndex;
  gv.DataBind();
}
protected void gvUsers_Sorting(object sender, GridViewSortEventArgs e)
{
  GridView gv = (GridView)sender;
  DataView dv = gv.DataSource as DataView;
  DataTable dataTable = dv.Table;
  String sortdir = "";
  if (e.SortExpression != "" & e.SortExpression != null)
  {
    if (gvSortExpression == e.SortExpression)
      gvSortDirection = GetSortDirection();
    else
      gvSortDirection = "ASC";
    gvSortExpression = e.SortExpression;
    gvUsers.EditIndex = -1;
  }
  gv.DataSource = GetSortedData(dataTable, e.SortExpression, gvSortDirection);
  gv.DataBind();
}
private String GetSortDirection()
{
  String newSortDirection = String.Empty;
  switch (gvSortDirection)
  {
    case "DESC":
        newSortDirection = "ASC";
        break;
    case "ASC":
        newSortDirection = "DESC";
        break;
  }
  return newSortDirection;
}
private DataView GetSortedData(DataTable dataTable, String SortExpression, String SortDirection)
{
  if (dataTable != null)
  {
    DataView dataView = new DataView(dataTable);

    if (SortExpression != "" && SortExpression != null)
        dataView.Sort = SortExpression + " " + SortDirection;

    // Add filter - You may add filter here
    return dataView;
  }
  return null;
}
protected void gvUsers_RowEditing(object sender, GridViewEditEventArgs e)
{
  GridView gv = (GridView)sender;
  DataView dv = gv.DataSource as DataView;
  DataTable dataTable = dv.Table;
  gv.DataSource = GetSortedData(dataTable, gvSortExpression, gvSortDirection);
  gv.EditIndex = e.NewEditIndex;
  gv.DataBind();
}