Clasificación GridView: SortDirection siempre Ascending

Tengo una vista en cuadrícula y necesito ordenar sus elementos cuando el usuario hace clic en el encabezado.
Su fuente de datos es un objeto List.

El aspx se define de esta manera:

       

El código detrás se define de esta manera:
Primera carga:

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

cuando el usuario hace clic en los encabezados:

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

Mi problema es que e.SortDirection siempre se establece en Ascendente.
Tengo una página web con un código similar y funciona bien, e.SortDirection alterna entre Ascendente y Descendente.

Qué hice mal ?

Puede usar una variable de sesión para almacenar la última expresión de clasificación y cuando clasifique la cuadrícula la próxima vez compare la expresión de clasificación de la cuadrícula con la variable de sesión que almacena la última expresión de clasificación. Si las columnas son iguales, verifique la dirección de la clasificación anterior y ordene en la dirección opuesta.

Ejemplo:

 DataTable sourceTable = GridAttendence.DataSource as DataTable; DataView view = new DataView(sourceTable); string[] sortData = Session["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"; } 

El problema con Session y Viewstate es que también debe realizar un seguimiento del control gridview para el que se almacena SortColumn y Direction si hay más de una vista de cuadrícula en la página.

Una alternativa a Session y Viewstate es agregar 2 atributos a Gridview y realizar un seguimiento de la columna y la dirección de esa manera.

Aquí hay un ejemplo:

 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"); } } 

Una solución simple:

 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; } 

Al igual que la clasificación predeterminada GridView y ligero en el ViewState.

USO:

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

La ordenación bidireccional automática solo funciona con la fuente de datos SQL. Desafortunadamente, toda la documentación en MSDN supone que está utilizando eso, por lo que GridView puede ser un poco frustrante.

La forma en que lo hago es hacer un seguimiento del pedido por mi cuenta. Por ejemplo:

  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(); } 

Este problema está ausente no solo con las fonts de datos SQL sino también con las fonts de datos de objeto. Sin embargo, al configurar DataSource dinámicamente en el código, es cuando esto sale mal. Desafortunadamente, MSDN a veces es muy pobre en información. Una simple mención de este comportamiento (esto no es un error sino un problema de diseño) ahorraría mucho tiempo. De todos modos, no estoy muy dispuesto a usar variables de Sesión para esto. Por lo general, almaceno la dirección de clasificación en un ViewState.

La forma en que hice esto es similar al código que me brindó la respuesta aceptada , pero es un poco diferente, así que pensé que podría publicarlo también. Tenga en cuenta que esta ordenación se realiza en una DataTable antes de que se vincule con la GridView .DataSource.

Opción uno: usar 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; } 

Opción dos: usar la sesión

Tenga en cuenta que se proporciona lo siguiente para fines heredados en el caso de que lo vea en el campo, o que aún respalda sistemas de la compañía que se dirigen a navegadores más antiguos.

 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; } 

¡No sé por qué todos olvidan usar campos ocultos! Son mucho más “baratos” que ViewState (que he apagado desde 2005). Si no desea usar Session o ViewState, esta es mi solución:

Coloque estos dos campos ocultos en su página aspx y coloque la clasificación predeterminada que desea para sus datos (estoy usando LastName por ejemplo):

   

Luego coloque este código auxiliar en su página Base (usted tiene una página base, ¿no?) Si no, ingrese su código .cs detrás).

 ///  /// 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 ///  /// The hidden field on page that has the PREVIOUS column that is sorted on /// The hidden field on page that has the PREVIOUS sort direction 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; } 

A continuación, debe gestionar la ordenación en su controlador de eventos de clasificación de cuadrícula. Llame al método anterior desde el controlador de eventos de clasificación, antes de llamar a su método principal que obtiene sus datos

 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); } 

Como hay tantos ejemplos que usan DataTables o DataViews u otras colecciones que no son LINQ friendly, pensé incluir un ejemplo de una llamada a un método de nivel medio que devuelve una lista genérica, y usar LINQ para hacer la clasificación con el fin de completar el ejemplo y hacerlo más “mundo real”:

 private void GetCases(AccountID accountId, string sortExpression, SortDirection sortDirection) { //get some data from a middle tier method (database etc._)( List 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(); } 

Por último, aquí está la clasificación descendente y sucia utilizando LINQ en una lista genérica de objetos personalizados. Estoy seguro de que hay algo más fantástico que hará el truco, pero esto ilustra el concepto:

static static Sort 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; } 

Por último, pero no menos importante (¿ya dije eso?) Es posible que desee poner algo como esto en su controlador Page_Load, de modo que la cuadrícula se enlace por defecto al cargar la página … Tenga en cuenta que _accountId es un parámetro querystring, convertido a una costumbre tipo de AccountID propio en este caso …

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

Toda esa respuesta no es del todo correcta. Yo uso eso:

 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); 

en gridView_Sorting …

Otro 🙂 No es necesario codificar los nombres de las columnas.

 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(); 

Ant entonces:

  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; } 

Se puede hacer sin el uso de View State o Session. El orden actual se puede determinar según el valor en la primera y la última fila de la columna que ordenamos:

  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() .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(); } 
        //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; } } 

Ha pasado un tiempo desde que utilicé GridView, pero creo que es necesario establecer la propiedad SortDirection de la grilla en lo que sea actualmente antes de abandonar el método OnSorting.

Asi que….

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

Me cansé de lidiar con este problema y puse la dirección de ordenación y columna de clasificación en ViewState ….

Para alternar entre ascendente y descendente, utilizo un método en la página base de mi aplicación para almacenar en caché la expresión de clasificación y la dirección de clasificación:

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

SortExpression y SortDirection son propiedades en BasePage que almacenan y recuperan sus valores de ViewState.

Entonces, todas mis páginas derivadas solo llaman a SetPageSort desde el método de ordenamiento de GridView y vinculan a GridView:

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

BindGrid comprueba SortExpression y lo utiliza y SortDirection para hacer un ORDER BY en el origen de datos de la cuadrícula, algo como esto:

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

Por lo tanto, la clase base ‘SetPageSort elimina gran parte del trabajo pesado de la ordenación GridView. Siento que me estoy olvidando de algo, pero esa es la idea general.

Probablemente apueste aquí, pero la solución que se me ocurrió es la que funciona mejor para mi situación:

El evento de carga de formulario se ve así:

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

Agregue dos campos ocultos a la página:

   

Agregue lo siguiente a su asp: Objeto GridView:

 AllowSorting="True" OnSorting="GridView1_Sorting" 

Utilice el siguiente evento de ordenación 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(); } 

Ahora, cada columna de mi vista de cuadrícula se ordena sin necesidad de cambios adicionales si alguna de las columnas cambia.

XML:

    

Código:

 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(); } } 

Esta es otra forma de resolver el problema:

 protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e) { List 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(); } 

Cadena vieja, pero tal vez mi respuesta ayudará a alguien.

Primero, obtenga su SqlDataSource como 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 

A continuación, utilice un método de extensión para el género (tipo de foto de chivo, pero un buen comienzo):

 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]; } } 

Usando la solución de SecretSquirrel arriba

aquí está mi código de producción completo. Simplemente cambie dgvCoaches a su nombre de vista de cuadrícula.

… durante la unión de la grilla

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

y ahora la clasificación

 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(); } } 

y aquí está el código aspx:

                     

Tuve un problema horrible con esto, así que finalmente recurrí al uso de LINQ para ordenar el DataTable antes de asignarlo a la vista:

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

En particular, encontré que los métodos DataView.Sort y DataGrid.Sort no son confiables al ordenar un campo booleano.

Espero que esto ayude a alguien por ahí.

 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(); } 

Quizás esto ayudará a alguien. No estoy seguro de si es porque es 2014 o no entiendo el problema que esta publicación intenta resolver, pero esto es muy simple con slickgrid de la siguiente manera:

El problema parece ser cómo “recordar” cuál es la configuración de clasificación actual, por lo que las sugerencias se basan en que Asp.Net tenga ese valor para usted. Sin embargo, slickGrid puede decirle cuál es el orden de clasificación actual:

Para alternar sort asc desc, puede usar grid.getSortColumns () para averiguar cuál es la clasificación de columna actualmente. Esto es lo que hice, pero solo estoy ordenando en 1 columna a la vez, así puedo hacer esto de manera segura: ‘if (grid.getSortColumns () [0] .sortAsc)’

… así que mi código que funciona es así:

  // 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 }, ]; 

.. carga tus datos como siempre, luego la parte de ordenación:

  // 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)); } 

Lastly make sure you have the SlickGrid image folder included in your site and you’ll get the asc/desc arrows appearing on the column when you select it. If they are missing the text will go italics but no arrows will appear.

Wrote this, it works for me:

  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; } 

In vb.net but very simple!

 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