Ordinamento GridView: SortDirection sempre crescente

Ho una griglia e ho bisogno di ordinare i suoi elementi quando l’utente fa clic sull’intestazione.
La sua origine dati è un object Elenco.

L’aspx è definito in questo modo:

       

Il codice sottostante è definito in questo modo:
Primo carico:

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

quando l’utente fa clic sulle intestazioni:

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

Il mio problema è che e.SortDirection è sempre impostato su Crescente.
Ho una pagina web con un codice simile e funziona bene, e.SortDirection si alterna tra Ascending e Descending.

Che cosa ho fatto di sbagliato ?

È ansible utilizzare una variabile di sessione per memorizzare l’espressione di ordinamento più recente e quando si ordina la griglia la volta successiva confrontare l’espressione di ordinamento della griglia con la variabile di sessione che memorizza l’ultima espressione di ordinamento. Se le colonne sono uguali, controllare la direzione del tipo precedente e ordinare nella direzione opposta.

Esempio:

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

Il problema con Session e Viewstate è che devi anche tenere traccia del controllo gridview per cui SortColumn e Direction sono memorizzati se c’è più di una gridview nella pagina.

Un’alternativa a Session e Viewstate consiste nell’aggiungere 2 attributi a Gridview e tenere traccia di Colonna e Direzione in questo modo.

Ecco un esempio:

 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 soluzione semplice:

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

Molto simile all’ordinamento GridView predefinito e leggero su 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(); } 

L’ordinamento bidirezionale automatico funziona solo con l’origine dati SQL. Sfortunatamente, tutta la documentazione di MSDN presuppone che tu stia usando quella, quindi GridView può diventare un po ‘frustrante.

Il modo in cui lo faccio è tenere traccia dell’ordine per conto mio. Per esempio:

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

Questo problema è assente non solo con origini dati SQL ma anche con origini dati object. Tuttavia, quando si imposta il DataSource in modo dinamico nel codice, è quando ciò va a male. Sfortunatamente, MSDN a volte è davvero molto povero di informazioni. Una semplice menzione di questo comportamento (questo non è un bug ma un problema di progettazione) farebbe risparmiare un sacco di tempo. Ad ogni modo, non sono molto propenso a usare le variabili Session per questo. Solitamente memorizzo la direzione di smistamento in un ViewState.

Il modo in cui l’ho fatto è simile al codice fornito dalla risposta accettata , bit è un po ‘diverso, quindi ho pensato di inserirlo anche lì. Si noti che questo ordinamento viene eseguito su un DataTable prima di essere associato a GridView .DataSource.

Opzione uno: utilizzo di 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; } 

Opzione due: utilizzo della sessione

Si noti che quanto segue viene fornito a fini legacy nel caso in cui lo si veda sul campo o che si stiano ancora supportando i sistemi aziendali destinati ai browser più vecchi.

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

Non so perché tutti si dimentichino dell’uso di campi nascosti! Sono così “meno costosi” di ViewState (che ho distriggersto dal 2005). Se non vuoi usare Session o ViewState, ecco la mia soluzione:

Metti questi due campi nascosti nella tua pagina aspx e inserisci l’ordinamento predefinito che desideri per i tuoi dati (sto usando LastName per esempio):

   

Quindi metti questo codice di supporto nella tua pagina Base (hai una pagina di base, no? In caso contrario, inserisci il codice .cs dietro).

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

Successivamente, è necessario gestire l’ordinamento nel gestore di eventi di ordinamento della griglia. Chiama il metodo precedente dal gestore dell’evento di ordinamento, prima di chiamare il metodo principale che ottiene i tuoi dati

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

Poiché molti esempi là fuori usano DataTables o DataView o altre raccolte non LINQ amichevoli, ho pensato di includere un esempio di chiamata a un metodo di livello intermedio che restituisce un elenco generico e utilizzare LINQ per eseguire l’ordinamento per completare l’esempio e renderlo più “mondo reale”:

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

Infine, ecco l’ordinamento down e dirty usando LINQ su un elenco generico di oggetti personalizzati. Sono certo che c’è qualcosa di più attraente là fuori che farà il trucco, ma questo illustra il concetto:

elenco statico privato Ordina (stringa 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; } 

Ultimo ma non meno importante (l’ho già detto?) Potresti voler inserire qualcosa di simile nel tuo gestore Page_Load, in modo che la griglia si leghi di default al caricamento della pagina … Nota che _accountId è un parametro querystring, convertito in una custom tipo di ID account personale in questo caso …

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

Tutte quelle risposte non sono completamente corrette. Io uso quello:

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

in gridView_Sorting …

Un altro 🙂 Non è necessario il nome della colonna del codice duro ..

 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 allora:

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

Può essere fatto senza l’uso di View State o Session. L’ordine corrente può essere determinato in base al valore nella prima e nell’ultima riga nella colonna che ordiniamo per:

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

È passato del tempo da quando ho utilizzato GridView, ma penso che sia necessario impostare la proprietà SortDirection della griglia su qualsiasi cosa sia attualmente prima di abbandonare il metodo OnSorting.

Così….

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

Mi sono stancato di affrontare questo problema e ho messo la direzione e la colonna di ordinamento nel ViewState ….

Per triggersre la funzione ascendente e discendente, utilizzo un metodo nella BasePage della mia app per memorizzare l’espressione di ordinamento e la direzione di ordinamento:

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

SortExpression e SortDirection sono entrambe proprietà in BasePage che memorizzano e recuperano i loro valori da ViewState.

Quindi tutte le mie pagine derivate chiamano SetPageSort dal metodo di ordinamento di GridView e collegano GridView:

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

BindGrid controlla SortExpression e lo usa e SortDirection per fare un ORDERY BY sull’origine dati della griglia, qualcosa del genere:

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

Quindi, la class base ‘SetPageSort rimuove gran parte del drudgery dell’ordinamento GridView. Mi sento come se stessi dimenticando qualcosa, ma questa è l’idea generale.

Probabilmente questo sta per scommettere sepolto qui, ma la soluzione che ho trovato è che funziona alla grande per la mia situazione:

L’evento di caricamento del modulo si presenta così:

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

Aggiungi due campi nascosti alla pagina:

   

Aggiungi il seguente al tuo asp: object GridView:

 AllowSorting="True" OnSorting="GridView1_Sorting" 

Utilizzare il seguente evento di ordinamento 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(); } 

Ora ogni colonna nella mia griglia è ordinata senza bisogno di ulteriori modifiche se una delle colonne cambia.

XML:

    

Codice:

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

Questo è un altro modo per risolvere il 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(); } 

Vecchia corda, ma forse la mia risposta aiuterà qualcuno.

Per prima cosa prendi il tuo SqlDataSource come un 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 

Quindi usa un metodo di estensione per l’ordinamento (tipo di colpo di testa, ma un buon inizio):

 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 soluzione di SecretSquirrel qui sopra

ecco il mio codice di produzione completo. Basta cambiare dgvCoaches con il nome della vista della griglia.

… durante il binding della griglia

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

e ora lo smistamento

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

e qui è il codice di aspx:

                     

Ho avuto un problema orribile con questo quindi ho finalmente fatto ricorso a LINQ per ordinare DataTable prima di assegnarlo alla vista:

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

In particolare, ho trovato i metodi DataView.Sort e DataGrid.Sort inaffidabili durante l’ordinamento di un campo booleano.

Spero che questo aiuti qualcuno là fuori.

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

Forse questo aiuterà qualcuno. Non sono sicuro se è perché è il 2014 o non capisco il problema che questo post cerca di risolvere ma questo è molto semplice con slickgrid come segue:

Il problema sembra essere come “ricordare” quale sia l’attuale impostazione di ordinamento, quindi i suggerimenti sono intorno a Asp.Net che contiene quel valore per te. Comunque slickGrid può dirti quale sia l’ordine corrente:

Per triggersre o distriggersre asc desc è ansible utilizzare grid.getSortColumns () per scoprire cosa è attualmente l’ordinamento della colonna. Questo è quello che ho fatto, ma sto solo ordinando 1 colonna alla volta, quindi posso tranquillamente farlo: ‘if (grid.getSortColumns () [0] .sortAsc)’

… quindi il mio codice che funziona è così:

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

.. carica i tuoi dati come al solito poi la parte ordinata:

  // 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