it-swarm.com.de

GridView-Sortierung: SortDirection immer aufsteigend

Ich habe eine Rasteransicht und muss die Elemente sortieren, wenn der Benutzer auf die Kopfzeile klickt.
Ihre Datenquelle ist ein Listenobjekt.

Der Aspx ist folgendermaßen definiert:

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

Der Code dahinter ist folgendermaßen definiert:
Erstes Laden:

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

wenn der Benutzer auf Kopfzeilen klickt:

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

Mein Problem ist, dass e.SortDirection immer auf Ascending gesetzt ist.
Ich habe eine Webseite mit einem ähnlichen Code und es funktioniert gut, e.SortDirection wechselt zwischen Ascending und Descending.

Was habe ich falsch gemacht ?

65
Julien N

Sie können eine Sitzungsvariable verwenden, um den neuesten Sortierausdruck zu speichern und beim nächsten Sortieren des Rasters den Sortierausdruck des Rasters mit der Sitzungsvariablen zu vergleichen, in der der letzte Sortierausdruck gespeichert ist. Wenn die Spalten gleich sind, überprüfen Sie die Richtung der vorherigen Sortierung und sortieren Sie in die entgegengesetzte Richtung. 

Beispiel:

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

Das Problem mit Session und Viewstate besteht darin, dass Sie auch das Rasteransicht-Steuerelement verfolgen müssen, für das SortColumn und Direction gespeichert sind, wenn sich auf der Seite mehr als eine Rasteransicht befindet.

Eine Alternative zu Session und Viewstate ist das Hinzufügen von zwei Attributen zu Gridview und das Nachverfolgen von Spalte und Richtung.

Hier ist ein Beispiel:

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

}
49
rwo

Eine einfache Lösung:

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

Ähnlich wie die standardmäßige GridView-Sortierung und die Leichtigkeit des ViewState.

VERWENDUNGSZWECK:

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

Die automatische bidirektionale Sortierung funktioniert nur mit der SQL-Datenquelle. Leider wird in der gesamten MSDN-Dokumentation davon ausgegangen, dass Sie das verwenden, sodass GridView etwas frustrierend werden kann.

Ich mache das so, indem ich die Reihenfolge selbst verfolge. Zum Beispiel:

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

Dieses Problem ist nicht nur bei SQL-Datenquellen, sondern auch bei Objektdatenquellen vorhanden. Wenn Sie die DataSource jedoch dynamisch im Code festlegen, wird dies zu einem Fehler. Leider ist MSDN manchmal sehr schlecht in Bezug auf Informationen. Eine einfache Erwähnung dieses Verhaltens (dies ist kein Fehler, sondern ein Designproblem) würde viel Zeit sparen. Jedenfalls bin ich nicht sehr geneigt, Session-Variablen dafür zu verwenden. Die Sortierrichtung speichere ich normalerweise in einem ViewState.

15
George

Die Art und Weise, wie ich das gemacht habe, ähnelt dem Code, den die akzeptierte Antwort bereitstellte, etwas anders, also dachte ich, ich würde es auch dort veröffentlichen. Beachten Sie, dass diese Sortierung nach einer DataTable erfolgt, bevor sie an die GridView . DataSource gebunden wird.

Option Eins: ViewState verwenden

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

Option Zwei: Session verwenden 

Beachten Sie, dass Folgendes für ältere Zwecke bereitgestellt wird, falls Sie es vor Ort sehen oder Sie weiterhin Unternehmenssysteme unterstützen, die auf ältere Browser abzielen.

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

Ich weiß nicht, warum alle vergessen, versteckte Felder zu verwenden! Sie sind so viel "billiger" als ViewState (den ich seit 2005 ausgeschaltet habe). Wenn Sie Session oder ViewState nicht verwenden möchten, ist hier meine Lösung:

Fügen Sie diese beiden ausgeblendeten Felder in Ihre Aspx-Seite ein und fügen Sie die gewünschte Standard-Sortierung für Ihre Daten ein (beispielsweise verwende ich LastName):

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

Dann fügen Sie diesen Hilfscode in Ihre Basisseite ein (Sie haben eine Basisseite, oder? Wenn nicht, geben Sie Ihren .cs-Code ein).

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

Als Nächstes müssen Sie die Sortierung in Ihrem Grid-Sortierereignishandler durchführen. Rufen Sie die obige Methode über den Sortierereignishandler auf, bevor Sie Ihre Hauptmethode aufrufen, die Ihre Daten abruft

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

Da so viele Beispiele DataTables oder DataViews oder andere nicht LINQ-freundliche Auflistungen verwenden, dachte ich, ich würde ein Beispiel für einen Aufruf einer Middle-Tier-Methode enthalten, die eine generische Liste zurückgibt, und LINQ verwenden, um die Sortierung abzurunden das Beispiel und machen es "realer Welt":

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

Als letztes wird hier eine Down-and-Dirty-Sortierung mit LINQ in einer generischen Liste benutzerdefinierter Objekte aufgeführt. Ich bin sicher, dass es etwas Schickeres gibt, das den Trick tun wird, aber dies veranschaulicht das Konzept:

private statische Listensortierung (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;
}

Zu guter Letzt (habe ich das schon gesagt?) Möchten Sie vielleicht etwas in Ihren PageLoad-Handler einfügen, damit das Raster beim Laden der Seite standardmäßig gebunden wird. Beachten Sie, dass _accountId ein Querystring-Parameter ist, der in einen benutzerdefinierten Wert konvertiert wird Typ der eigenen AccountID in diesem Fall ...

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

Noch eine :) Die Spaltennamen müssen nicht hart codiert werden.

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

Ameise dann:

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

All diese Antwort ist nicht ganz richtig. Ich benutze das:

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

3
in4man_1

Dies kann ohne View State oder Session erfolgen. Die aktuelle Reihenfolge kann basierend auf dem Wert in der ersten und letzten Zeile in der Spalte ermittelt werden, in der wir sortieren:

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

Das wird wahrscheinlich hier begraben liegen, aber die Lösung, die ich mir ausgedacht habe, ist für meine Situation gut geeignet:

Das Formularladeereignis sieht folgendermaßen aus:

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

Fügen Sie der Seite zwei ausgeblendete Felder hinzu:

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

Fügen Sie Ihrem asp: GridView-Objekt Folgendes hinzu:

AllowSorting="True" OnSorting="GridView1_Sorting"

Verwenden Sie das folgende GridView-Sortierereignis

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

Jetzt wird jede Spalte in meiner Rasteransicht sortiert, ohne dass weitere Änderungen erforderlich sind, wenn sich eine der Spalten ändert.

2
Dave Lucre
        <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;
    }
}
2
AVIK GHOSH

Ich habe es satt, mich mit diesem Problem auseinanderzusetzen und die Sortierrichtung und Sortierspalte in den ViewState zu setzen.

1

Alte Saite, aber vielleicht hilft meine Antwort jemandem.

Holen Sie sich zuerst Ihre SqlDataSource als 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

Verwenden Sie dann eine Erweiterungsmethode für die Sortierung (eine Art billiger Schuss, aber einen guten Start):

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

Um aufsteigend und absteigend umzuschalten, verwende ich eine Methode in BasePage meiner App, um den Sortierausdruck und die Sortierrichtung zwischenzuspeichern:

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

SortExpression und SortDirection sind beide Eigenschaften in BasePage, die ihre Werte von ViewState speichern und abrufen.

Alle meine abgeleiteten Seiten rufen also einfach SetPageSort von der Sortiermethode der GridView auf und binden die GridView:

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

BindGrid prüft die SortExpression und verwendet sie und SortDirection, um ORDERY BY für die Datenquelle des Grids auszuführen, etwa wie folgt:

if (SortExpression.Length > 0)
{
    qry.ORDER_BY(SortExpression + " " + SortDirection);
}

gv.DataSource = qry.ExecuteReader();
gv.DataBind();

Die SetPageSort-Basisklasse beseitigt also einen Großteil der Plackerei der GridView-Sortierung. Ich habe das Gefühl, etwas zu vergessen, aber das ist die allgemeine Idee.

1
djuth

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

Code:

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

Verwendung von SecretSquirrel's Lösung oben

hier ist mein voll funktionsfähiger Produktionscode. Ändern Sie einfach dgvCoaches in den Namen Ihrer Rasteransicht.

... während der Bindung des Gitters

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

und jetzt die Sortierung

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

und hier ist der Aspx-Code:

<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>
1
PCPGMR

Es ist schon eine Weile her, dass ich eine GridView verwendet habe, aber ich denke, Sie müssen die SortDirection-Eigenschaft der Tabelle auf den aktuellen Wert setzen, bevor Sie die OnSorting-Methode verlassen.

Damit....

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

1

Dies ist eine andere Möglichkeit, das Problem zu lösen:

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

Ich hatte ein schreckliches Problem damit, und schließlich habe ich LINQ zum Bestellen der DataTable verwendet, bevor sie der Ansicht zugewiesen wurde:

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

Insbesondere die Methoden DataView.Sort und DataGrid.Sort halte ich beim Sortieren eines booleschen Felds für unzuverlässig. 

Ich hoffe, das hilft jemandem da draußen.

0
Daver

Schrieb das, es funktioniert für mich: 

 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;
    }
0
Rasmus W
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();
}
0
Basil

Vielleicht hilft das jemandem. Nicht sicher, ob es sich um 2014 handelt oder ich nicht das Problem verstehe, das dieser Beitrag versucht zu lösen, aber dies ist mit Slickgrid wie folgt sehr einfach:

Das Problem scheint zu sein, wie man sich an die aktuelle Sortierungseinstellung „erinnert“, also gibt es Vorschläge für Asp.Net, die diesen Wert für Sie behalten. SlickGrid kann Ihnen jedoch die aktuelle Sortierreihenfolge mitteilen:

Um die Sortierung aufsteigend zu ändern, können Sie grid.getSortColumns () verwenden, um herauszufinden, wie die Spaltensortierung aktuell ist. Dies ist, was ich getan habe, aber ich sortiere immer nur nach einer Spalte, also kann ich dies sicher tun: 'if (grid.getSortColumns () [0] .sortAsc)'

... also mein Code, der funktioniert, ist so:

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

.. laden Sie Ihre Daten wie gewohnt und sortieren Sie danach:

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

Vergewissern Sie sich schließlich, dass der SlickGrid-Imageordner in Ihrer Site enthalten ist. Wenn Sie ihn auswählen, werden die Auf-/Abwärtspfeile in der Spalte angezeigt. Wenn sie fehlen, wird der Text kursiv dargestellt, aber es erscheinen keine Pfeile.

0
Barry McDermid

So mache ich es. Viel einfacher als viele Antworten hier IMO:

Erstellen Sie diese SortDirection-Klasse

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

Und dann verwenden Sie es in Ihrer Sortierfunktion wie folgt:

            // 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;
                } 
            }
0
Isaac Byrne