title: Manual sorting for gridview in vb.net
body: <p>I have done research on how to manually create sorting in a grid-view and none of it is thorough enough for me to follow.  I need more of a step by step solution, like what event should my sorting code go in, how would i enable the headers to allow sorting. normally, i just have .net do this but for some reason this time it doesn't allow it, maybe because i am not using a datasource.</p>
  
  <p>that's my code that creates a datable and then binds to the gridview.</p>
  
  <pre><code>Function toptable()
  
  
          Dim reader As SqlDataReader
          cmd.Parameters.AddWithValue("@yeartoget", DropDownList1.SelectedValue)
          cmd.Parameters.AddWithValue("@mode", RadioButtonList1.SelectedValue)
  
          If TextBox1.Text = "" Then
              Dim d As Date = Date.Today
              TextBox1.Text = d.AddDays(-1)
  
          End If
  
          Dim pyear As Date
          Dim pyear1 As Date
          pyear = TextBox1.Text
          Dim year1 As Int16
          year1 = (pyear.Year - DropDownList1.SelectedValue)
  
          If pyear.Year &lt;&gt; Now.Year Then
              pyear1 = (pyear.AddYears(-(year1 + 1)))
  
          Else
              pyear1 = (pyear.AddYears(-year1))
          End If
  
  
  
          cmd.Parameters.AddWithValue("@current", TextBox1.Text)
          cmd.Parameters.AddWithValue("@search", pyear1)
          cmd.CommandText = "asoftour"
          cmd.CommandType = CommandType.StoredProcedure
          cmd.Connection = conn
          cmd.CommandTimeout = 300
          conn.Open()
          reader = cmd.ExecuteReader()
  
          mytable.clear()
  
          myTable.Load(reader)
  
          conn.Close()
  
  
          Dim currentppax As New DataColumn
          currentppax = New DataColumn("AVGPPAX", GetType(Double))
          currentppax.Expression = "IIf([CurrentPAX] = 0, 0, [CurrentSales] / [CurrentPAX])"
  
          Dim selectedppax As New DataColumn
          selectedppax = New DataColumn("AVGpPAX1", GetType(Double))
          selectedppax.Expression = "IIf([asofPAX] = 0, 0, [asofSales] / [asofPAX])"
  
          Dim projsales As New DataColumn
          projsales = New DataColumn("ProjSales", GetType(Double))
          projsales.Expression = "IIF([PercentSales] = 0, [CurrentSales], [CurrentSales] / [PercentSales])"
  
          Dim projpax As New DataColumn
          projpax = New DataColumn("ProjPAX", GetType(Double))
          ' projpax.Expression = "IIF([PercentPAX] = 0, [CurrentPAX], [CurrentPAX] / [percentpax] )"
          projpax.Expression = "IIF([PercentPAX] =  0, [CurrentPAX], [CurrentPAX] / [percentpax] )"
  
          Dim remainingsales As New DataColumn
          remainingsales = New DataColumn("remainingsales", GetType(Double))
          remainingsales.Expression = "ProjSales - currentsales"
  
          Dim remainingpax As New DataColumn
          remainingpax = New DataColumn("remainingpax", GetType(Double))
          remainingpax.Expression = "Projpax - currentpax"
  
          Dim movementpax As New DataColumn
          movementpax = New DataColumn("movementPAX", GetType(Double))
          movementpax.Expression = "IIF([ASOFPAX] = 0, 2,(CurrentPAX / [ASOFPAX]))-1"
  
          Dim movementsales As New DataColumn
          movementsales = New DataColumn("movementsales", GetType(Double))
          movementsales.Expression = "IIF([ASOFsales] = 0, 2,(Currentsales / [ASOFsales]))-1"
  
  
          myTable.Columns.Add(selectedppax)
          myTable.Columns.Add(currentppax)
          myTable.Columns.Add(projsales)
          myTable.Columns.Add(projpax)
          myTable.Columns.Add(remainingsales)
          myTable.Columns.Add(remainingpax)
          myTable.Columns.Add(movementsales)
          myTable.Columns.Add(movementpax)
  
          GridView1.DataSource = myTable
          GridView1.DataBind()
          Dim row As New GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal)
  
          'spanned cell that will span the columns I don't want to give the additional header 
          Dim compare As TableCell = New TableHeaderCell()
          compare.ColumnSpan = 8
          row.Cells.Add(compare)
          compare.Text = DropDownList1.Text
  
  
          'spanned cell that will span the columns i want to give the additional header
          Dim current As TableCell = New TableHeaderCell()
          current.ColumnSpan = 3
          current.Text = Year(Now())
          row.Cells.Add(current)
  
          Dim Projection As TableCell = New TableHeaderCell()
          Projection.ColumnSpan = 4
          Projection.Text = "Projections"
          row.Cells.Add(Projection)
  
          Dim Movements As TableCell = New TableHeaderCell()
          Movements.ColumnSpan = 2
          Movements.Text = "Movement"
          row.Cells.Add(Movements)
  
          'Add the new row to the gridview as the master header row
          'A table is the only Control (index[0]) in a GridView
          DirectCast(GridView1.Controls(0), Table).Rows.AddAt(0, row)
  </code></pre>
  
  <p>And thats my client side code</p>
  
  <pre><code>                    &lt;asp:GridView ID="GridView1" runat="server" CellPadding="4" ForeColor="#333333" GridLines="None" CellSpacing="2" AutoGenerateColumns="False" ShowFooter="True" Font-Size="Smaller" AllowSorting="True" OnRowDataBound="GridView1_RowDataBound" OnSorting="GridView1_Sorting"&gt;
                          &lt;RowStyle BackColor="#EFF3FB" /&gt;
                          &lt;FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /&gt;
                          &lt;PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" /&gt;
                          &lt;SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" /&gt;
                          &lt;HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /&gt;
                          &lt;EditRowStyle BackColor="#2461BF" /&gt;
                          &lt;AlternatingRowStyle BackColor="White" /&gt;
                          &lt;Columns&gt;
                              &lt;asp:TemplateField FooterText="Totals:" HeaderText="Regions"&gt;
                                  &lt;EditItemTemplate&gt;
                                      &lt;asp:TextBox ID="TextBox1" runat="server" Text='&lt;%# Bind("Tour") %&gt;'&gt;&lt;/asp:TextBox&gt;
                                  &lt;/EditItemTemplate&gt;
                                  &lt;ItemTemplate&gt;
                                      &lt;asp:Label ID="Label1" runat="server" Text='&lt;%# Bind("Tour") %&gt;'&gt;&lt;/asp:Label&gt;
                                  &lt;/ItemTemplate&gt;
                                  &lt;FooterStyle Font-Bold="True" /&gt;
                              &lt;/asp:TemplateField&gt;
  
  &lt;asp:TemplateField HeaderText="As Of Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#Getsales(Decimal.Parse(Eval("asofsales").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#Getsales1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  &lt;asp:TemplateField HeaderText="YE Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#Getyesales(Decimal.Parse(Eval("yesales").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#Getyesales1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  &lt;asp:TemplateField HeaderText="PCT Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetAvesales(Decimal.Parse(Eval("percentSales").ToString())).ToString("P1")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetAvesales1().ToString("P1")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;      
  
  
  
  &lt;asp:TemplateField HeaderText="As Of PAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#Getpax(Decimal.Parse(Eval("asofpax").ToString())).ToString("N0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#Getpax1().ToString("N0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  
   &lt;asp:TemplateField HeaderText="YE PAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#Getyepax(Decimal.Parse(Eval("YEpax").ToString())).ToString("N0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#Getyepax1().ToString("N0")%&gt;
  &lt;/FooterTemplate&gt;
       &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  &lt;asp:TemplateField HeaderText="PCT PAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetAvepax(Decimal.Parse(Eval("percentpax").ToString())).ToString("P2")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetAvepax1().ToString("P1")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;      
  
  
  &lt;asp:TemplateField HeaderText="AVG PPAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetAveppax(Decimal.Parse(Eval("AVGppax1").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetpreviousAveppax1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
  &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;                           
  
  
  
  &lt;asp:TemplateField HeaderText="Current Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetCsales(Decimal.Parse(Eval("CurrentSales").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetCsales1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  
  &lt;asp:TemplateField HeaderText="Current PAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetCpax(Decimal.Parse(Eval("CurrentPAX").ToString())).ToString("N0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetCpax1().ToString("N0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  
                              &lt;asp:TemplateField HeaderText="AVG PPAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetAveppax(Decimal.Parse(Eval("AVGppax").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetAveppax1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
                                  &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  &lt;asp:TemplateField HeaderText="Proj. Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetPsales(Decimal.Parse(Eval("ProjSales").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetPsales1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  &lt;asp:TemplateField HeaderText="Proj. PAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetPpax(Decimal.Parse(Eval("ProjPax").ToString())).ToString("N0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetPpax1().ToString("N0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  
  &lt;asp:TemplateField HeaderText="Remaining Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetRPsales(Decimal.Parse(Eval("remainingsales").ToString())).ToString("C0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetRPsales1().ToString("C0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  &lt;asp:TemplateField HeaderText="Remaining PAX"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#GetRPpax(Decimal.Parse(Eval("RemainingPax").ToString())).ToString("N0")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#GetRPpax1().ToString("N0")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;                                             
  
  
  &lt;asp:TemplateField HeaderText="PCT. Pax"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#Getmovepax(Decimal.Parse(Eval("movementPAX").ToString())).ToString("P1")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  
  &lt;%#Getmovepax1().ToString("P1")%&gt;
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
  
  &lt;asp:TemplateField HeaderText="PCT. Sales"&gt;
  &lt;ItemTemplate&gt;
   &lt;%#Getmovesales(Decimal.Parse(Eval("movementsales").ToString())).ToString("P1")%&gt;
  &lt;/ItemTemplate&gt;
  &lt;FooterTemplate&gt;
  &lt;%#Getmovesales1().ToString("P1")%&gt;
  
  &lt;/FooterTemplate&gt;
      &lt;FooterStyle Font-Bold="True" /&gt;
  &lt;/asp:TemplateField&gt;
                              &lt;asp:TemplateField HeaderText="Theme"&gt;
                                  &lt;ItemTemplate&gt;
                                      &lt;asp:Label ID="lbltheme" runat="server" Text="Label"&gt;&lt;/asp:Label&gt;&lt;br /&gt;
                                  &lt;/ItemTemplate&gt;
                              &lt;/asp:TemplateField&gt;
  
                          &lt;/Columns&gt;                     
                      &lt;/asp:GridView&gt;
  </code></pre>
  
  <p>This is what i tried but no links show on my headers.</p>
  
  <pre><code> Public Property GridViewSortDirection() As SortDirection
  
  
          Get
  
  
              If ViewState("sortDirection") Is Nothing Then
  
                  ViewState("sortDirection") = SortDirection.Ascending
              End If
  
  
              Return DirectCast(ViewState("sortDirection"), SortDirection)
          End Get
  
          Set(ByVal value As SortDirection)
              ViewState("sortDirection") = value
          End Set
      End Property
  
      Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As GridViewSortEventArgs)
  
  
          Dim sortExpression As String = e.SortExpression
  
          If GridViewSortDirection = SortDirection.Ascending Then
  
  
              GridViewSortDirection = SortDirection.Descending
  
  
              SortGridView(sortExpression, SortDirection.Descending)
          Else
  
  
  
              GridViewSortDirection = SortDirection.Ascending
  
  
              SortGridView(sortExpression, SortDirection.Ascending)
          End If
  
      End Sub
  
      Private Sub SortGridView(ByVal sortExpression As String, ByVal direction As String)
  
  
          ' You can cache the DataTable for improving performance
  
          Dim dv As New DataView(myTable)
  
          dv.Sort = sortExpression &amp; direction
  
          GridView1.DataSource = dv
  
          GridView1.DataBind()
  
      End Sub
  </code></pre>