title: Multiple column sorting in Gridview?
body: <p>Hi I want to Sort Multiple column In a gridview like shown here 
  <a href="https://stackoverflow.com/questions/1429261/hierarchical-multi-column-sorting-for-the-net-gridview">Hierarchical (Multi-column) Sorting for the .net GridView?</a></p>
  
  <p>I did my home work 
  My aspx looks like </p>
  
  <pre><code>&lt;%@ Page Language="C#" AutoEventWireup="True" CodeBehind="Default.aspx.cs" Inherits="_Default" %&gt;
  
  &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
  
  &lt;html xmlns="http://www.w3.org/1999/xhtml" &gt;
  &lt;head id="Head1" runat="server"&gt;
      &lt;title&gt;Multiple sorting with Gridview&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;form id="form1" runat="server"&gt;
      &lt;div&gt;
          &lt;asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True" 
              AllowSorting="true" onsorting="GridView1_Sorting" style="margin-right: 541px" 
              Width="873px"&gt;
          &lt;/asp:GridView&gt;
          &lt;p&gt;&lt;asp:Label runat="server" ID="lblSortExpression" /&gt;&lt;/p&gt;
      &lt;/div&gt;
      &lt;/form&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>In my Aspx.cs page </p>
  
  <pre><code>using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Data;
  using System.Diagnostics;
  using System.Collections.Specialized;
  using System.Text;
  using System.Web.UI.WebControls;
  using System.Data.SqlClient;
  
  partial class _Default : System.Web.UI.Page
  {
  
      private ListDictionary m_ldSortExpression;
      private ListDictionary SortExpressions
      {
          get
          {
              m_ldSortExpression = (ListDictionary)ViewState["SortExpressions"];
              if (m_ldSortExpression == null)
              {
                  m_ldSortExpression = new ListDictionary();
              }
              return m_ldSortExpression;
          }
          set { ViewState["SortExpressions"] = value; }
      }
  
      protected void Page_Load(object sender, System.EventArgs e)
      {
          if (!IsPostBack)
          {
              BindData();
          }
      }
  
      public void BindData()
      {
          // Usually you would get the data from the database.
          // To simplify the code, I will just fill a datatable with some standard data.
          DataTable dt = new DataTable();
          dt.Columns.Add("FirstName");
          dt.Columns.Add("LastName");
          dt.Columns.Add("Age");
          dt.Columns.Add("Position");
  
          dt.Rows.Add(new object[] {
              "1",
              "2",
              28,
              "5"
          });
          dt.Rows.Add(new object[] {
              "2",
              "8",
              31,
              "2"
          });
          dt.Rows.Add(new object[] {
              "2",
              "4",
              31,
              "4"
          });
          dt.Rows.Add(new object[] {
              "3",
              "7",
              37,
              "3"
          });
          dt.Rows.Add(new object[] {
              "4",
              "4",
              40,
              "1"
          });
  
          DataView dv = dt.DefaultView;
          // use a stringbuilder to hold the sortexpression for the dataview
          StringBuilder sbSortExpression = new StringBuilder();
          if (SortExpressions.Count &gt; 0)
          {
              string[] myKeys = new string[SortExpressions.Count + 1];
              SortExpressions.Keys.CopyTo(myKeys, 0);
              for (int i = 0; i &lt;= SortExpressions.Count - 1; i++)
              {
                  sbSortExpression.Append(myKeys[i]);
                  sbSortExpression.Append(" ");
                  sbSortExpression.Append(SortExpressions[myKeys[i]]);
                  if (i != SortExpressions.Count - 1)
                  {
                      sbSortExpression.Append(", ");
                  }
  
              }
              lblSortExpression.Text = sbSortExpression.ToString();
  
              // usually we would send that sort-expression now to SQL via some stored-procedure
              dv.Sort = sbSortExpression.ToString();
          }
          else
          {
              lblSortExpression.Text = string.Empty;
          }
  
          GridView1.DataSource = dv;
          GridView1.DataBind();
          PositionGlyph(GridView1, dv.Sort.ToString(), dt);
  
  
      }
  
      private void PositionGlyph(GridView GridView1, string p,DataTable dt)
      {
          if ((GridView1.Rows.Count == 0) || (string.IsNullOrEmpty(p)))
              return;
  
          Image glyph = new Image();
          glyph.EnableTheming = false;
  
          string[] words = p.Split(',');
  
          foreach (string word in words)
          {
              string[] SortType = word.Split(' ');
              if (SortType[SortType.Length - 1] == SortOrder.Ascending.ToString().Substring(0, 3).ToUpper())
                  glyph.ImageUrl = "~/Images/down_arrow.png";
  
              else
                  glyph.ImageUrl = "~/Images/up_arrow.png";
  
              int columnindex = dt.Columns[SortType[SortType.Length - 2].ToString()].Ordinal;
              GridView1.HeaderRow.Cells[columnindex].Controls.Add(glyph);
              //for (int x = 0; x &lt; dt.Columns.Count; x++)
              //{
              //    if (SortType[SortType.Length - 2].ToString()== dt.Columns[x].ColumnName)
              //    {
              //        GridView1.HeaderRow.Cells[x].Controls.Add(glyph);
              //        break;
              //    }
              //}
  
          }
  
      }
  
      protected void GridView1_Sorting(object sender, System.Web.UI.WebControls.GridViewSortEventArgs e)
      {
          m_ldSortExpression = SortExpressions;
  
          if (!m_ldSortExpression.Contains(e.SortExpression))
          {
              m_ldSortExpression.Add(e.SortExpression, e.SortDirection.ToString().Replace("Ascending", "ASC").Replace("Descending", "DESC"));
          }
          else
          {
              // Get sort direction
              string strSortDirection = m_ldSortExpression[e.SortExpression].ToString();
              // Was it ascending?
              if (strSortDirection == "ASC")
              {
                  // Yes, so sort in desc
                  m_ldSortExpression[e.SortExpression] = "DESC";
              }
              else if (strSortDirection == "DESC")
              {
                  // it is descending
                  // remove the sort order
                  m_ldSortExpression.Remove(e.SortExpression);
              }
          }
  
          SortExpressions = m_ldSortExpression;
          BindData();
      }
      public _Default()
      {
          Load += Page_Load;
      }
  
  }
  </code></pre>
  
  <p>Everything is working fine even multiple sorting but sort arrow in column header is not showing properly.I think issue is in PositionGlyph Method.Asc or Desc arrow is showing only for last clicked header.I want to show sort direction for all the columns.Please help me on the same </p>