【问题标题】:GridView sorting: SortDirection always AscendingGridView 排序:SortDirection 总是升序
【发布时间】:2010-09-19 23:39:57
【问题描述】:

我有一个网格视图,当用户单击标题时,我需要对其元素进行排序。
它的数据源是一个 List 对象。

aspx 是这样定义的:

<asp:GridView ID="grdHeader" AllowSorting="true" AllowPaging="false" 
    AutoGenerateColumns="false" Width="780" runat="server"  OnSorting="grdHeader_OnSorting" EnableViewState="true">
    <Columns>
        <asp:BoundField DataField="Entitycode" HeaderText="Entity" SortExpression="Entitycode" />
        <asp:BoundField DataField="Statusname" HeaderText="Status" SortExpression="Statusname" />
        <asp:BoundField DataField="Username" HeaderText="User" SortExpression="Username" />
    </Columns>
</asp:GridView>

后面的代码是这样定义的:
第一次加载:

protected void btnSearch_Click(object sender, EventArgs e)
{
    List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
    this.grdHeader.DataSource = items;
    this.grdHeader.DataBind();
}

当用户点击标题时:

protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e)
{
    List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
    items.Sort(new Helpers.GenericComparer<V_ReportPeriodStatusEntity>(e.SortExpression, e.SortDirection));
    grdHeader.DataSource = items;
    grdHeader.DataBind();
}

我的问题是 e.SortDirection 总是设置为 Ascending。
我有一个类似代码的网页,它运行良好,e.SortDirection 在升序和降序之间交替。

我做错了什么?

【问题讨论】:

    标签: asp.net sorting gridview


    【解决方案1】:

    自从我使用 GridView 已经有一段时间了,但我认为您需要在离开 OnSorting 方法之前将网格的 SortDirection 属性设置为当前的任何值。

    所以....

    List&lt;V_ReportPeriodStatusEntity&gt; items = GetPeriodStatusesForScreenSelection();
    items.Sort(new Helpers.GenericComparer&lt;V_ReportPeriodStatusEntity&gt;(e.SortExpression, e.SortDirection));
    grdHeader.SortDirection = e.SortDirection.Equals(SortDirection.Ascending) ? SortDirection.Descending : SortDirection.Ascending;
    grdHeader.DataSource = items;
    grdHeader.DataBind();

    【讨论】:

    • 不错的建议,但 SortDirection 是只读的,所以它不起作用。所以我认为是正确的:ASP.NET 应该设置这个值...
    【解决方案2】:

    我厌倦了处理这个问题并将排序方向和排序列放在 ViewState 中......

    【讨论】:

      【解决方案3】:

      为了切换升序和降序,我在应用的 BasePage 中使用了一个方法来缓存排序表达式和排序方向:

      protected void SetPageSort(GridViewSortEventArgs e)
      {
          if (e.SortExpression == SortExpression)
          {
              if (SortDirection == "ASC")
              {
                  SortDirection = "DESC";
              }
              else
              {
                  SortDirection = "ASC";
              }
          }
          else
          {
              SortDirection = "ASC";
              SortExpression = e.SortExpression;
          }
      }
      

      SortExpression 和 SortDirection 都是 BasePage 中的属性,它们在 ViewState 中存储和检索它们的值。

      所以我所有的派生页面都只是从 GridView 的 Sorting 方法中调用 SetPageSort,并绑定 GridView:

      protected void gv_Sorting(object sender, GridViewSortEventArgs e)
      {
          SetPageSort(e);
          BindGrid();
      }
      

      BindGrid 检查 SortExpression 并使用它和 SortDirection 对网格的数据源执行 ORDERY BY,如下所示:

      if (SortExpression.Length > 0)
      {
          qry.ORDER_BY(SortExpression + " " + SortDirection);
      }
      
      gv.DataSource = qry.ExecuteReader();
      gv.DataBind();
      

      因此,基类的 SetPageSort 消除了 GridView 排序的大部分繁琐工作。我觉得我忘记了什么,但这是一般的想法。

      【讨论】:

        【解决方案4】:

        自动双向排序仅适用于 SQL 数据源。不幸的是,MSDN 中的所有文档都假定您正在使用它,因此 GridView 可能会有点令人沮丧。

        我这样做的方式是自己跟踪订单。例如:

            protected void OnSortingResults(object sender, GridViewSortEventArgs e)
            {
                // If we're toggling sort on the same column, we simply toggle the direction. Otherwise, ASC it is.
                // e.SortDirection is useless and unreliable (only works with SQL data source).
                if (_sortBy == e.SortExpression)
                    _sortDirection = _sortDirection == SortDirection.Descending ? SortDirection.Ascending : SortDirection.Descending;
                else
                    _sortDirection = SortDirection.Ascending;
        
                _sortBy = e.SortExpression;
        
                BindResults();
            }
        

        【讨论】:

          【解决方案5】:

          您可以使用会话变量来存储最新的排序表达式,并在下次对网格进行排序时将网格的排序表达式与存储上次排序表达式的会话变量进行比较。如果列相等,则检查先前排序的方向并按相反方向排序。

          示例:

          DataTable sourceTable = GridAttendence.DataSource as DataTable;
          DataView view = new DataView(sourceTable);
          string[] sortData = ViewState["sortExpression"].ToString().Trim().Split(' ');
          if (e.SortExpression == sortData[0])
          {
              if (sortData[1] == "ASC")
              {
                  view.Sort = e.SortExpression + " " + "DESC";
                  this.ViewState["sortExpression"] = e.SortExpression + " " + "DESC";
              }
              else
              {
                  view.Sort = e.SortExpression + " " + "ASC";
                  this.ViewState["sortExpression"] = e.SortExpression + " " + "ASC";
              }
          }
          else
          {
              view.Sort = e.SortExpression + " " + "ASC";
              this.ViewState["sortExpression"] = e.SortExpression + " " + "ASC";
          }
          

          【讨论】:

          • 确实 - 上面的代码错误,如果在不同的浏览器选项卡中同时查看两个网格,则会中断。用 ViewState 替换 Session。
          • tomfanning 是正确的,当打开同一页面的两个实例时,此代码将提供意外结果。
          • @tommfannnig 您可以说代码错误,因为没有将SortExpression 存储在 viewstate 中。但是您必须解释如何将表达式存储在视图状态中(尤其是当GridView 的视图状态关闭时)
          【解决方案6】:

          这个问题不仅存在于 SQL 数据源中,也存在于对象数据源中。但是,当在代码中动态设置 DataSource 时,就会出现问题。不幸的是,MSDN 有时信息真的很贫乏。简单提及此行为(这不是错误,而是设计问题)将节省大量时间。无论如何,我不太愿意为此使用 Session 变量。我通常将排序方向存储在 ViewState 中。

          【讨论】:

          • 在我看来,这是迄今为止最好的答案。使用 ObjectDataSource 绑定您的数据并设置 dataSourceId 而不是在后面的代码中使用旧学校。如果您确实需要存储排序方向,请将其放在 ViewState 而不是 Session 中。
          【解决方案7】:

          我这样做的方式类似于accepted answer 提供的代码,有点不同,所以我想我也会把它放在那里。请注意,此排序是在 DataTable 绑定到 GridView.DataSource 之前进行的。

          选项一:使用 ViewState

          void DataGrid_Sorting(object sender, GridViewSortEventArgs e)
          {
              if (e.SortExpression == (string)ViewState["SortColumn"])
              {
                  // We are resorting the same column, so flip the sort direction
                  e.SortDirection = 
                      ((SortDirection)ViewState["SortColumnDirection"] == SortDirection.Ascending) ? 
                      SortDirection.Descending : SortDirection.Ascending;
              }
              // Apply the sort
              this._data.DefaultView.Sort = e.SortExpression +
                  (string)((e.SortDirection == SortDirection.Ascending) ? " ASC" : " DESC");
              ViewState["SortColumn"] = e.SortExpression;
              ViewState["SortColumnDirection"] = e.SortDirection;
          }
          

          选项二:使用会话

          请注意,如果您在现场看到以下内容,或者您​​仍在支持针对旧版浏览器的公司系统,则提供以下内容是出于遗留目的。

          void DataGrid_Sorting(object sender, GridViewSortEventArgs e)
          {
              if (e.SortExpression == (string)HttpContext.Current.Session["SortColumn"])
              {
                  // We are resorting the same column, so flip the sort direction
                  e.SortDirection = 
                      ((SortDirection)HttpContext.Current.Session["SortColumnDirection"] == SortDirection.Ascending) ? 
                      SortDirection.Descending : SortDirection.Ascending;
              }
              // Apply the sort
              this._data.DefaultView.Sort = e.SortExpression +
                  (string)((e.SortDirection == SortDirection.Ascending) ? " ASC" : " DESC");
              HttpContext.Current.Session["SortColumn"] = e.SortExpression;
              HttpContext.Current.Session["SortColumnDirection"] = e.SortDirection;
          }
          

          【讨论】:

          • 不!使用视图状态!会话中断跨浏览器选项卡功能。
          • @tomfanning - 是时候有人告诉我为什么这会降低投票率。 :) 上面的代码是旧的(注意日期),当时我们只针对应用程序的 IE6,所以我添加了另一个选项,代码使用 ViewState 代替。顺便说一句,我们实际上已经转移到 ASP.NET MVC,这不是问题,因为我们使用 jQuery 来处理排序客户端。
          • @rob 我仍然建议您删除 Session[] 实现,因为它会导致多个浏览器窗口/选项卡出现不可预知的行为。
          • @tomfanning - 是的,但如果有人遇到遗留代码中的格式,我不想只是删除它,因为它确实服务于历史目的。
          【解决方案8】:

          一个简单的解决方案:

          protected SortDirection GetSortDirection(string column)
          {
              SortDirection nextDir = SortDirection.Ascending; // Default next sort expression behaviour.
              if (ViewState["sort"] != null && ViewState["sort"].ToString() == column)
              {   // Exists... DESC.
                  nextDir = SortDirection.Descending;
                  ViewState["sort"] = null;
              }
              else
              {   // Doesn't exists, set ViewState.
                  ViewState["sort"] = column;
              }
              return nextDir;
          }
          

          很像默认的 GridView 排序和 ViewState 上的轻量级。

          用法:

          protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e)
          {
              List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
          
              items.Sort(new Helpers.GenericComparer<V_ReportPeriodStatusEntity>(e.SortExpression, GetSortDirection(e.SortExpression));
              grdHeader.DataSource = items;
              grdHeader.DataBind();
          }
          

          【讨论】:

            【解决方案9】:

            Session 和 Viewstate 的问题在于,如果页面上有多个 gridview,您还必须跟踪存储 SortColumn 和 Direction 的 gridview 控件。

            Session 和 Viewstate 的替代方法是向 Gridview 添加 2 个属性并以此方式跟踪 Column 和 Direction。

            这是一个例子:

            private void GridViewSortDirection(GridView g, GridViewSortEventArgs e, out SortDirection d, out string f)
            {
                f = e.SortExpression;
                d = e.SortDirection;
            
                //Check if GridView control has required Attributes
                if (g.Attributes["CurrentSortField"] != null && g.Attributes["CurrentSortDir"] != null)
                {
                    if (f == g.Attributes["CurrentSortField"])
                    {
                        d = SortDirection.Descending;
                        if (g.Attributes["CurrentSortDir"] == "ASC")
                        {
                            d = SortDirection.Ascending;
                        }
                    }
            
                    g.Attributes["CurrentSortField"] = f;
                    g.Attributes["CurrentSortDir"] = (d == SortDirection.Ascending ? "DESC" : "ASC");
                }
            
            }
            

            【讨论】:

            • 我喜欢你的属性替代视图状态。
            • @Lijo 这就是:
            • @rwo 优秀的解决方案!赞!对于新手:必须从为 gridview 的 OnSorting 事件分配的事件处理程序中调用此方法。
            • 不涉及会话/视图状态的优秀方法,谢谢。
            【解决方案10】:

            我遇到了一个可怕的问题,所以我最终求助于使用 LINQ 在将 DataTable 分配给视图之前对其进行排序:

            Dim lquery = From s In listToMap
                         Select s
                         Order By s.ACCT_Active Descending, s.ACCT_Name
            

            在对布尔字段进行排序时,我确实发现 DataView.Sort 和 DataGrid.Sort 方法不可靠。

            我希望这对那里的人有所帮助。

            【讨论】:

              【解决方案11】:

              所有答案都不完全正确。我用那个:

              protected void SetPageSort(GridViewSortEventArgs e) 
                      { 
                          if (e.SortExpression == SortExpression) 
                          { 
                              if (SortDirection == "ASC") 
                              { 
                                  SortDirection = "DESC"; 
                              } 
                              else 
                              { 
                                  SortDirection = "ASC"; 
                              } 
                          } 
                          else 
                          {
                              if (SortDirection == "ASC")
                              {
                                  SortDirection = "DESC";
                              }
                              else
                              {
                                  SortDirection = "ASC";
                              } 
                              SortExpression = e.SortExpression; 
                          } 
                      } 
                protected void gridView_Sorting(object sender, GridViewSortEventArgs e)
                      {
                          SetPageSort(e); 
              

              在gridView_Sorting中...

              【讨论】:

                【解决方案12】:
                void dg_SortCommand(object source, DataGridSortCommandEventArgs e)
                {
                    DataGrid dg = (DataGrid) source;
                    string sortField = dg.Attributes["sortField"];
                    List < SubreportSummary > data = (List < SubreportSummary > ) dg.DataSource;
                    string field = e.SortExpression.Split(' ')[0];
                    string sort = "ASC";
                    if (sortField != null)
                    {
                        sort = sortField.Split(' ')[0] == field ? (sortField.Split(' ')[1] == "DESC" ? "ASC" : "DESC") : "ASC";
                    }
                    dg.Attributes["sortField"] = field + " " + sort;
                    data.Sort(new GenericComparer < SubreportSummary > (field, sort, null));
                    dg.DataSource = data;
                    dg.DataBind();
                }
                

                【讨论】:

                  【解决方案13】:
                          <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" AllowSorting="True" 
                              onsorting="GridView1_Sorting" EnableViewState="true">
                              <Columns><asp:BoundField DataField="bookid" HeaderText="BOOK ID" SortExpression="bookid"  />
                                  <asp:BoundField DataField="bookname" HeaderText="BOOK NAME" />
                                  <asp:BoundField DataField="writer" HeaderText="WRITER" />
                                  <asp:BoundField DataField="totalbook" HeaderText="TOTAL BOOK" SortExpression="totalbook"  />
                                  <asp:BoundField DataField="availablebook" HeaderText="AVAILABLE BOOK" />
                  //gridview code on page load under ispostback false//after that.
                  
                  
                  
                  protected void Page_Load(object sender, EventArgs e)
                      {
                          if (!IsPostBack)
                          {
                              string query = "SELECT * FROM book";
                              DataTable DT = new DataTable();
                              SqlDataAdapter DA = new SqlDataAdapter(query, sqlCon);
                              DA.Fill(DT);
                  
                  
                              GridView1.DataSource = DT;
                              GridView1.DataBind();
                          }
                      }
                  
                      protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
                      {
                  
                          string query = "SELECT * FROM book";
                          DataTable DT = new DataTable();
                          SqlDataAdapter DA = new SqlDataAdapter(query, sqlCon);
                          DA.Fill(DT);
                  
                          GridView1.DataSource = DT;
                          GridView1.DataBind();
                  
                          if (DT != null)
                          {
                  
                              DataView dataView = new DataView(DT);
                              dataView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection);
                  
                  
                              GridView1.DataSource = dataView;
                              GridView1.DataBind();
                          }
                      }
                  
                      private string GridViewSortDirection
                      {
                          get { return ViewState["SortDirection"] as string ?? "DESC"; }
                          set { ViewState["SortDirection"] = value; }
                      }
                  
                      private string ConvertSortDirectionToSql(SortDirection sortDirection)
                      {
                          switch (GridViewSortDirection)
                          {
                              case "ASC":
                                  GridViewSortDirection = "DESC";
                                  break;
                  
                              case "DESC":
                                  GridViewSortDirection = "ASC";
                                  break;
                          }
                  
                          return GridViewSortDirection;
                      }
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    这可能会被埋在这里,但我想出的解决方案非常适合我的情况:

                    表单加载事件如下所示:

                    private DataTable DataTable1;
                    protected void Page_Load(object sender, EventArgs e)
                    {
                      DataTable1 = GetDataFromDatabase();
                      this.GridView1.DataSource = DataTable1.DefaultView;
                      this.GridView1.DataBind();
                    }
                    

                    在页面上添加两个隐藏字段:

                    <asp:HiddenField runat="server" ID="lastSortDirection" />
                    <asp:HiddenField runat="server" ID="lastSortExpression" />
                    

                    将以下内容添加到您的 asp:GridView 对象中:

                    AllowSorting="True" OnSorting="GridView1_Sorting"
                    

                    使用下面的 GridView 排序事件

                    protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
                    {
                        if (lastSortExpression.Value == e.SortExpression.ToString())
                        {
                            if (lastSortDirection.Value == SortDirection.Ascending.ToString())
                            {
                                e.SortDirection = SortDirection.Descending;
                            }
                            else
                            {
                                e.SortDirection = SortDirection.Ascending;
                            }
                            lastSortDirection.Value = e.SortDirection.ToString();
                            lastSortExpression.Value = e.SortExpression;
                        }
                        else
                        {
                            lastSortExpression.Value = e.SortExpression;
                            e.SortDirection = SortDirection.Ascending;
                            lastSortDirection.Value = e.SortDirection.ToString();
                        }
                    
                        DataView dv = DataTable1.DefaultView;
                        if (e.SortDirection == SortDirection.Ascending)
                        {
                            dv.Sort = e.SortExpression;
                        }
                        else
                        {
                            dv.Sort = e.SortExpression + " DESC";
                        }
                    
                        DataTable1 = dv.ToTable();
                        GridView1.DataSource = DataTable1.DefaultView;
                        GridView1.DataBind();
                    }
                    

                    现在,如果任何列发生变化,我的 gridview 中的每一列都已排序,无需任何进一步的更改。

                    【讨论】:

                      【解决方案15】:

                      XML:

                      <asp:BoundField DataField="DealCRMID" HeaderText="Opportunity ID"
                       SortExpression="DealCRMID"/>
                      <asp:BoundField DataField="DealCustomerName" HeaderText="Customer" 
                       SortExpression="DealCustomerName"/>
                      <asp:BoundField DataField="SLCode" HeaderText="Practice" 
                       SortExpression="SLCode"/>
                      

                      代码:

                      private string ConvertSortDirectionToSql(String sortExpression,SortDirection sortDireciton)
                      {
                          switch (sortExpression)
                          {
                              case "DealCRMID":
                                   ViewState["DealCRMID"]=ChangeSortDirection(ViewState["DealCRMID"].ToString());
                                   return ViewState["DealCRMID"].ToString();
                      
                              case "DealCustomerName":
                                   ViewState["DealCustomerName"] = ChangeSortDirection(ViewState["DealCustomerName"].ToString());
                                   return ViewState["DealCustomerName"].ToString();
                      
                              case "SLCode":
                                   ViewState["SLCode"] = ChangeSortDirection(ViewState["SLCode"].ToString());
                                   return ViewState["SLCode"].ToString();
                      
                              default:
                                  return "ASC";
                          }       
                      }
                      
                      private string ChangeSortDirection(string sortDireciton)
                      {
                          switch (sortDireciton)
                          {
                              case "DESC":
                                  return "ASC";
                              case "ASC":
                                  return "DESC";
                              default:
                                  return "ASC";
                          }
                      }
                      
                      protected void gvPendingApprovals_Sorting(object sender, GridViewSortEventArgs e)
                      {
                          DataSet ds = (System.Data.DataSet)(gvPendingApprovals.DataSource);
                      
                          if(ds.Tables.Count>0)
                          {
                              DataView m_DataView = new DataView(ds.Tables[0]);
                              m_DataView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql   (e.SortExpression.ToString(), e.SortDirection);
                      
                              gvPendingApprovals.DataSource = m_DataView;
                              gvPendingApprovals.DataBind();
                          }
                      }
                      

                      【讨论】:

                        【解决方案16】:

                        这是解决问题的另一种方法:

                        protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e)
                        {
                            List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
                            items.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e);
                            grdHeader.DataSource = items;
                            grdHeader.DataBind();
                        }
                        
                        private string ConvertSortDirectionToSql(GridViewSortEventArgs e)
                        {
                            ViewState[e.SortExpression] = ViewState[e.SortExpression] ?? "ASC";
                            ViewState[e.SortExpression] = (ViewState[e.SortExpression].ToString() == "ASC") ? "DESC" : "ASC";
                            return ViewState[e.SortExpression].ToString();
                        }
                        

                        【讨论】:

                          【解决方案17】:

                          另一个 :) 不需要对列名进行硬编码..

                          DataTable dt = GetData();
                          
                              SortDirection sd;
                              string f;
                              GridViewSortDirection(gvProductBreakdown, e, out sd, out f);
                              dt.DefaultView.Sort = sd == SortDirection.Ascending ? f + " asc" : f + " desc";
                              gvProductBreakdown.DataSource = dt;
                              gvProductBreakdown.DataBind();
                          

                          蚂蚁然后:

                           private void GridViewSortDirection(GridView g, GridViewSortEventArgs e, out SortDirection d, out string f)
                              {
                                  f = e.SortExpression;
                                  d = e.SortDirection;
                           if (g.Attributes[f] != null)
                                  {
                                      d = g.Attributes[f] == "ASC" ? SortDirection.Descending : SortDirection.Ascending;
                          
                                      g.Attributes[f] = d == SortDirection.Ascending ? "ASC" : "DESC";
                                  }
                                  else
                                  {
                                      g.Attributes[f] = "ASC";
                                      d = SortDirection.Ascending;
                                  }
                          

                          【讨论】:

                            【解决方案18】:

                            它可以在不使用 View State 或 Session 的情况下完成。当前顺序可以根据我们排序的列的第一行和最后一行的值来确定:

                                    protected void gvItems_Sorting(object sender, GridViewSortEventArgs e)
                                {
                                    GridView grid = sender as GridView; // get reference to grid
                                    SortDirection currentSortDirection = SortDirection.Ascending; // default order
                            
                                    // get column index by SortExpression
                                    int columnIndex = grid.Columns.IndexOf(grid.Columns.OfType<DataControlField>()
                                                                  .First(x => x.SortExpression == e.SortExpression));
                            
                                    // sort only if grid has more than 1 row
                                    if (grid.Rows.Count > 1)
                                    {
                                        // get cells
                                        TableCell firstCell = grid.Rows[0].Cells[columnIndex];
                                        TableCell lastCell = grid.Rows[grid.Rows.Count - 1].Cells[columnIndex];
                            
                                        // if field type of the cell is 'TemplateField' Text property is always empty.
                                        // Below assumes that value is binded to Label control in 'TemplateField'.
                                        string firstCellValue = firstCell.Controls.Count == 0 ? firstCell.Text : ((Label)firstCell.Controls[1]).Text;
                                        string lastCellValue = lastCell.Controls.Count == 0 ? lastCell.Text : ((Label)lastCell.Controls[1]).Text;
                            
                                        DateTime tmpDate;
                                        decimal tmpDecimal;
                            
                                        // try to determinate cell type to ensure correct ordering
                                        // by date or number
                                        if (DateTime.TryParse(firstCellValue, out tmpDate)) // sort as DateTime
                                        {
                                            currentSortDirection = 
                                                DateTime.Compare(Convert.ToDateTime(firstCellValue), 
                                                                 Convert.ToDateTime(lastCellValue)) < 0 ? 
                                                                        SortDirection.Ascending : SortDirection.Descending;
                                        }
                                        else if (Decimal.TryParse(firstCellValue, out tmpDecimal)) // sort as any numeric type
                                        {
                                            currentSortDirection = Decimal.Compare(Convert.ToDecimal(firstCellValue), 
                                                                                   Convert.ToDecimal(lastCellValue)) < 0 ? 
                                                                                   SortDirection.Ascending : SortDirection.Descending;
                                        }
                                        else // sort as string
                                        {
                                            currentSortDirection = string.CompareOrdinal(firstCellValue, lastCellValue) < 0 ? 
                                                                                         SortDirection.Ascending : SortDirection.Descending;
                                        }
                                    }
                            
                                    // then bind GridView using correct sorting direction (in this example I use Linq)
                                    if (currentSortDirection == SortDirection.Descending)
                                    {
                                        grid.DataSource = myItems.OrderBy(x => x.GetType().GetProperty(e.SortExpression).GetValue(x, null));
                                    }
                                    else
                                    {
                                        grid.DataSource = myItems.OrderByDescending(x => x.GetType().GetProperty(e.SortExpression).GetValue(x, null));
                                    }
                            
                                    grid.DataBind();
                                }
                            

                            【讨论】:

                              【解决方案19】:

                              旧字符串,但也许我的回答会对某人有所帮助。

                              首先将您的 SqlDataSource 作为 DataView:

                              Private Sub DataGrid1_SortCommand(ByVal source As Object, ByVal e As DataGridSortCommandEventArgs) Handles grid1.SortCommand
                                  Dim dataView As DataView = CType(SqlDataSource1.Select(DataSourceSelectArguments.Empty), DataView)
                                  dataView.Sort = e.SortExpression + dataView.FieldSortDirection(Session, e.SortExpression)
                              
                                  grid1.DataSourceID = Nothing
                                  grid1.DataSource = dataView
                                  grid1.DataBind()
                              
                              End Sub
                              

                              然后使用扩展方法进行排序(有点小气,但一个好的开始):

                              public static class DataViewExtensions
                              {
                                  public static string FieldSortDirection(this DataView dataView, HttpSessionState session, string sortExpression)
                                  {
                                      const string SORT_DIRECTION = "SortDirection";
                                      var identifier = SORT_DIRECTION + sortExpression;
                              
                                      if (session[identifier] != null)
                                      {
                                          if ((string) session[identifier] == " ASC")
                                              session[identifier] = " DESC";
                                          else if ((string) session[identifier] == " DESC")
                                              session[identifier] = " ASC";
                                      }
                                      else
                                          session[identifier] = " ASC";
                              
                                      return (string) session[identifier];
                                  }
                              }
                              

                              【讨论】:

                                【解决方案20】:

                                也许这会对某人有所帮助。不确定是因为它是 2014 年,还是我不明白这篇文章试图解决的问题,但这对于 slickgrid 来说非常简单,如下所示:

                                问题似乎是如何“记住”当前的排序设置,因此建议围绕 Asp.Net 为您保留该值。然而 slickGrid 可以告诉你当前的排序顺序是什么:

                                要切换 asc desc 排序,您可以使用 grid.getSortColumns() 来找出当前的列排序。这就是我所做的,但我一次只对 1 列进行排序,因此我可以安全地这样做:'if(grid.getSortColumns()[0].sortAsc)'

                                ...所以我的代码是这样的:

                                    // Make sure you have sortable: true on the relevant column names or 
                                    // nothing happens as I found!!
                                    var columns = [
                                    { name: "FileName", id: "FileName", field: "FileName", width: 95, selectable: true, sortable: true },
                                    { name: "Type", id: "DocumentType", field: "DocumentType", minWidth: 105, width: 120, maxWidth: 120, selectable: true, sortable: true },
                                    { name: "ScanDate", id: "ScanDate", field: "ScanDate", width: 90, selectable: true, sortable: true }, ];
                                

                                .. 像往常一样加载您的数据,然后是排序部分:

                                   // Clicking on a column header fires this event. Here we toggle the sort direction
                                    grid.onHeaderClick.subscribe(function(e, args) {
                                        var columnID = args.column.id;
                                
                                        if (grid.getSortColumns()[0].sortAsc) {
                                            grid.setSortColumn(args.column.id, true);
                                        }
                                        else {
                                            grid.setSortColumn(args.column.id, false);
                                        }
                                    });
                                
                                    // The actual sort function is like this 
                                        grid.onSort.subscribe(function (e, args) {
                                            sortdir = args.sortAsc ? 1 : -1;
                                            sortcol = args.sortCol.field;
                                
                                            //alert('in sort');
                                
                                            // using native sort with comparer
                                            // preferred method but can be very slow in IE with huge datasets
                                            dataView.sort(comparer, args.sortAsc);
                                            grid.invalidateAllRows();
                                            grid.render();
                                        });
                                
                                // Default comparer is enough for what I'm doing here ..
                                function comparer(a, b) {
                                    var x = a[sortcol], y = b[sortcol];
                                    return (x == y ? 0 : (x > y ? 1 : -1));
                                }
                                

                                最后确保您的站点中包含 SlickGrid 图像文件夹,当您选择它时,列上会出现 asc/desc 箭头。如果缺少它们,文本将变为斜体,但不会出现箭头。

                                【讨论】:

                                  【解决方案21】:

                                  我不知道为什么每个人都忘记了使用隐藏字段!它们比 ViewState(我从 2005 年开始关闭)“便宜”得多。如果您不想使用 Session 或 ViewState,那么这是我的解决方案:

                                  将这两个隐藏字段放在您的 aspx 页面上,并为您的数据设置您想要的默认排序(例如,我使用 LastName):

                                  <asp:HiddenField ID="hfSortExpression" runat="server" Value="LastName" />
                                  <asp:HiddenField ID="hfSortDirection" runat="server" Value="Ascending" />
                                  

                                  然后把这个帮助代码放在你的基本页面中(你有一个基本页面不是吗?如果没有,把你的 .cs 代码放在后面)。

                                  /// <summary>
                                  /// Since native ASP.Net GridViews do not provide accurate SortDirections, 
                                  /// we must save a hidden field with previous sort Direction and Expression.
                                  /// Put these two hidden fields on page and call this method in grid sorting event
                                  /// </summary>
                                  /// <param name="hfSortExpression">The hidden field on page that has the PREVIOUS column that is sorted on</param>
                                  /// <param name="hfSortDirection">The hidden field on page that has the PREVIOUS sort direction</param>
                                  protected SortDirection GetSortDirection(GridViewSortEventArgs e, HiddenField hfSortExpression, HiddenField hfSortDirection)
                                  {
                                      //assume Ascending always by default!!
                                      SortDirection sortDirection = SortDirection.Ascending;
                                  
                                      //see what previous column (if any) was sorted on
                                      string previousSortExpression = hfSortExpression.Value;
                                      //see what previous sort direction was used
                                      SortDirection previousSortDirection = !string.IsNullOrEmpty(hfSortDirection.Value) ? ((SortDirection)Enum.Parse(typeof(SortDirection), hfSortDirection.Value)) : SortDirection.Ascending;
                                  
                                      //check if we are now sorting on same column
                                      if (e.SortExpression == previousSortExpression)
                                      {
                                          //check if previous direction was ascending
                                          if (previousSortDirection == SortDirection.Ascending)
                                          {
                                              //since column name matches but direction doesn't, 
                                              sortDirection = SortDirection.Descending;
                                          }
                                      }
                                  
                                      // save them back so you know for next time
                                      hfSortExpression.Value = e.SortExpression;
                                      hfSortDirection.Value = sortDirection.ToString();
                                  
                                      return sortDirection;
                                  }
                                  

                                  接下来,您需要在网格排序事件处理程序中处理排序。在调用获取数据的 main 方法之前,从排序事件处理程序调用上述方法

                                  protected void gridContacts_Sorting(object sender, GridViewSortEventArgs e)
                                  {
                                      //get the sort direction (since GridView sortDirection is not implemented!)
                                      SortDirection sortDirection = GetSortDirection(e, hfSortExpression, hfSortDirection);
                                  
                                      //get data, sort and rebind (obviously, this is my own method... you must replace with your own)
                                      GetCases(_accountId, e.SortExpression, sortDirection);
                                  }
                                  

                                  由于有这么多示例使用 DataTables 或 DataViews 或其他非 LINQ 友好的集合,我想我会包含一个示例,即调用返回通用列表的中间层方法,并使用 LINQ 按顺序进行排序完善示例并使其更加“真实世界”:

                                  private void GetCases(AccountID accountId, string sortExpression, SortDirection sortDirection)
                                  {
                                      //get some data from a middle tier method (database etc._)(
                                      List<PendingCase> pendingCases = MyMiddleTier.GetCasesPending(accountId.Value);
                                      //show a count to the users on page (this is just nice to have)
                                      lblCountPendingCases.Text = pendingCases.Count.ToString();
                                      //do the actual sorting of your generic list of custom objects
                                      pendingCases = Sort(sortExpression, sortDirection, pendingCases);
                                      //bind your grid
                                      grid.DataSource = pendingCases;
                                      grid.DataBind();
                                  }
                                  

                                  最后,这里是使用 LINQ 对自定义对象的通用列表进行的向下和脏排序。我敢肯定有一些更高级的东西可以解决问题,但这说明了这个概念:

                                  private static List Sort(string sortExpression, SortDirection sortDirection, List pendingCases) {

                                      switch (sortExpression)
                                      {
                                          case "FirstName":
                                              pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.FirstName).ToList() : pendingCases.OrderByDescending(c => c.FirstName).ToList();
                                              break;
                                          case "LastName":
                                              pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.LastName).ToList() : pendingCases.OrderByDescending(c => c.LastName).ToList();
                                              break;
                                          case "Title":
                                              pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.Title).ToList() : pendingCases.OrderByDescending(c => c.Title).ToList();
                                              break;
                                          case "AccountName":
                                              pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.AccountName).ToList() : pendingCases.OrderByDescending(c => c.AccountName).ToList();
                                              break;
                                          case "CreatedByEmail":
                                              pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.CreatedByEmail).ToList() : pendingCases.OrderByDescending(c => c.CreatedByEmail).ToList();
                                              break;
                                          default:
                                              break;
                                      }
                                      return pendingCases;
                                  }
                                  

                                  最后但同样重要的是(我说过了吗?)您可能希望在 Page_Load 处理程序中放置类似的内容,以便网格在页面加载时默认绑定...请注意,_accountId 是一个查询字符串参数,已转换在这种情况下,我自己的自定义类型的 AccountID...

                                      if (!Page.IsPostBack)
                                      {
                                          //sort by LastName ascending by default
                                          GetCases(_accountId,hfSortExpression.Value,SortDirection.Ascending);
                                      }
                                  

                                  【讨论】:

                                  • 我也喜欢使用隐藏字段,您可以使用 jQuery/js 访问它们。我使用了你的前两组代码。效果很好。我的 Linq 东西是在这里使用 Batishchev 的方法完成的:link
                                  【解决方案22】:

                                  使用 SecretSquirrel 的solution above

                                  这是我完整的工作代码。只需将 dgvCoaches 更改为您的网格视图名称即可。

                                  ...在网格的绑定过程中

                                          dgvCoaches.DataSource = dsCoaches.Tables[0];
                                          ViewState["AllCoaches"] = dsCoaches.Tables[0];
                                          dgvCoaches.DataBind();
                                  

                                  现在是排序

                                  protected void gridView_Sorting(object sender, GridViewSortEventArgs e)
                                  {
                                      DataTable dt = ViewState["AllCoaches"] as DataTable;
                                  
                                      if (dt != null)
                                      {
                                          if (e.SortExpression == (string)ViewState["SortColumn"])
                                          {
                                              // We are resorting the same column, so flip the sort direction
                                              e.SortDirection =
                                                  ((SortDirection)ViewState["SortColumnDirection"] == SortDirection.Ascending) ?
                                                  SortDirection.Descending : SortDirection.Ascending;
                                          }
                                          // Apply the sort
                                          dt.DefaultView.Sort = e.SortExpression +
                                              (string)((e.SortDirection == SortDirection.Ascending) ? " ASC" : " DESC");
                                          ViewState["SortColumn"] = e.SortExpression;
                                          ViewState["SortColumnDirection"] = e.SortDirection; 
                                  
                                          dgvCoaches.DataSource = dt;
                                          dgvCoaches.DataBind();
                                      }
                                  }
                                  

                                  这是aspx代码:

                                  <asp:GridView ID="dgvCoaches" runat="server" 
                                      CssClass="table table-hover table-striped" GridLines="None"  DataKeyNames="HealthCoachID" OnRowCommand="dgvCoaches_RowCommand"
                                      AutoGenerateColumns="False" OnSorting="gridView_Sorting" AllowSorting="true">
                                      <Columns>
                                          <asp:BoundField DataField="HealthCoachID" Visible="false" />
                                          <asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName" />
                                          <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" />
                                          <asp:BoundField DataField="LoginName" HeaderText="Login Name" SortExpression="LoginName" />
                                          <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" HtmlEncode="false" DataFormatString="<a href=mailto:{0}>{0}</a>" />
                                          <asp:TemplateField>
                                              <ItemTemplate>
                                                      <asp:LinkButton runat="server" BorderStyle="None" CssClass="btn btn-default" Text="<i class='glyphicon glyphicon-edit'></i>" CommandName="Update" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
                                              </ItemTemplate>
                                          </asp:TemplateField>
                                          <asp:TemplateField>
                                              <ItemTemplate>
                                                  <asp:LinkButton runat="server" OnClientClick="return ConfirmOnDelete();" BorderStyle="None" CssClass="btn btn-default" Text="<i class='glyphicon glyphicon-remove'></i>" CommandName="Delete" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
                                              </ItemTemplate>
                                          </asp:TemplateField>
                                      </Columns>
                                      <RowStyle CssClass="cursor-pointer" />
                                  </asp:GridView>
                                  

                                  【讨论】:

                                    【解决方案23】:

                                    在 vb.net 中但是很简单!

                                    Protected Sub grTicketHistory_Sorting(sender As Object, e As GridViewSortEventArgs) Handles grTicketHistory.Sorting
                                    
                                        Dim dt As DataTable = Session("historytable")
                                        If Session("SortDirection" & e.SortExpression) = "ASC" Then
                                            Session("SortDirection" & e.SortExpression) = "DESC"
                                        Else
                                            Session("SortDirection" & e.SortExpression) = "ASC"
                                        End If
                                        dt.DefaultView.Sort = e.SortExpression & " " & Session("SortDirection" & e.SortExpression)
                                        grTicketHistory.DataSource = dt
                                        grTicketHistory.DataBind()
                                    
                                    End Sub
                                    

                                    【讨论】:

                                      【解决方案24】:

                                      写这个,对我有用:

                                       protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
                                          {
                                              if (ViewState["sortExpression"] == null || ViewState["sortExpression"].ToString() != e.SortExpression.ToString())
                                                  MyDataTable.DefaultView.Sort = e.SortExpression + " ASC";
                                              else
                                              {
                                                  if (ViewState["SortDirection"].ToString() == "Ascending")
                                                      MyDataTable.DefaultView.Sort = e.SortExpression = e.SortExpression + " DESC";
                                                  else
                                                      MyDataTable.DefaultView.Sort = e.SortExpression + " ASC";
                                              }
                                      
                                              GridView1.DataSource = MyDataTable;
                                              GridView1.DataBind();
                                      
                                              ViewState["sortExpression"] = e.SortExpression;
                                              ViewState["SortDirection"] = e.SortDirection;
                                          }
                                      

                                      【讨论】:

                                      • 尝试添加更多解释。
                                      • 您能否强调一下您的实现与提问者之间的区别?
                                      【解决方案25】:

                                      这是我的做法。比 IMO 的很多答案要容易得多:

                                      创建这个 SortDirection 类

                                          // ==================================================
                                          // SortByDirection
                                          // ==================================================
                                          public SortDirection SortByDirection
                                          {
                                              get
                                              {
                                                  if (ViewState["SortByDirection"] == null)
                                                  {
                                                      ViewState["SortByDirection"] = SortDirection.Ascending;
                                                  }
                                      
                                                  return (SortDirection)Enum.Parse(typeof(SortDirection), ViewState["SortByDirection"].ToString());
                                              }
                                              set { ViewState["SortByDirection"] = value; }
                                          }
                                      

                                      然后像这样在你的排序函数中使用它:

                                                  // Created Date
                                                  if (sortBy == "CreatedDate")
                                                  {
                                                      if (SortByDirection == SortDirection.Ascending)
                                                      {
                                                          data = data.OrderBy(x => x.CreatedDate).ToList();
                                                          SortByDirection = SortDirection.Descending;
                                                      }
                                                      else {
                                                          data = data.OrderByDescending(x => x.CreatedDate).ToList();
                                                          SortByDirection = SortDirection.Ascending;
                                                      } 
                                                  }
                                      

                                      【讨论】:

                                        【解决方案26】:
                                        protected void gv_Sorting(object sender, GridViewSortEventArgs e)
                                        {
                                            DataTable dataTable = (DataTable)Cache["GridData"];
                                        
                                            if (dataTable != null)
                                            {
                                                DataView dataView = new DataView(dataTable);
                                                string Field1 = e.SortExpression;
                                                string whichWay = "ASC";
                                                if (HttpContext.Current.Session[Field1] != null)
                                                {
                                                    whichWay = HttpContext.Current.Session[Field1].ToString();
                                                    if (whichWay == "ASC")
                                                        whichWay = "DESC";
                                                    else
                                                        whichWay = "ASC";               
                                                }
                                        
                                                HttpContext.Current.Session[Field1] = whichWay;
                                                dataView.Sort = Field1 + " " + whichWay;      
                                                gv.DataSource = dataView;
                                                gv.DataBind();
                                            }
                                        }
                                        

                                        并且您存储之前检索到的信息

                                            string SqlConn = ConfigurationManager.ConnectionStrings["Sql28"].ConnectionString;
                                            SqlConnection sqlcon = new SqlConnection(SqlConn);
                                            sqlcon.Open();
                                        
                                            SqlCommand cmd = new SqlCommand();
                                            cmd.Connection = sqlcon;
                                            cmd.CommandType = System.Data.CommandType.Text;
                                            cmd.CommandText = HttpContext.Current.Session["sql"].ToString();
                                        
                                            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                                            DataTable employees = new DataTable();
                                            adapter.Fill(employees);
                                        
                                            gv.DataSource = employees;
                                            gv.DataBind();
                                        
                                            Cache.Insert("GridData", employees, null, System.Web.Caching.Cache.NoAbsoluteExpiration,new TimeSpan(0, 360000, 0));
                                        

                                        【讨论】:

                                          猜你喜欢
                                          • 2016-02-26
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 2016-07-31
                                          • 1970-01-01
                                          相关资源
                                          最近更新 更多