Сортировка GridView: SortDirection всегда по возрастанию

У меня есть gridview, и мне нужно отсортировать его элементы, когда пользователь нажимает на заголовок.
Его источником данных является объект List.

Aspx определяется следующим образом:

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

Код позади определяется следующим образом:
Первая загрузка:

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

когда пользователь нажимает на заголовки:

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

Моя проблема в том, что для e.SortDirection всегда установлено значение Ascending. У меня есть веб-страница с похожим кодом, и она работает хорошо, e.SortDirection чередуется между восходящим и нисходящим.

Что я сделал не так?

Ответ 1

Вы можете использовать переменную сеанса для хранения последнего выражения сортировки и при следующей сортировке сетки сравнить выражение сортировки сетки с переменной сеанса, в которой хранится последнее выражение сортировки. Если столбцы равны, проверьте направление предыдущей сортировки и сортируйте в обратном направлении.

Пример:

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

Ответ 2

Проблема с Session и ViewState заключается в том, что вам также нужно отслеживать элемент управления gridview, для которого SortColumn и Direction сохраняются, если на странице имеется несколько gridview.

Альтернативой Session и Viewstate является добавление 2 атрибутов в Gridview и отслеживание столбца и направления таким образом.

Вот пример:

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

}

Ответ 3

Простое решение:

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

Очень похож на сортировку по умолчанию GridView по умолчанию и легкий на ViewState.

ПРИМЕНЕНИЕ:

protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e)
{
    List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();

    items.Sort(new Helpers.GenericComparer<V_ReportPeriodStatusEntity>(e.SortExpression, GetSortDirection(e.SortExpression));
    grdHeader.DataSource = items;
    grdHeader.DataBind();
}

Ответ 4

Автоматическая двунаправленная сортировка работает только с источником данных SQL. К сожалению, вся документация в MSDN предполагает, что вы используете это, поэтому GridView может немного расстраивать.

Как я это делаю, отслеживая заказ самостоятельно. Например:

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

        _sortBy = e.SortExpression;

        BindResults();
    }

Ответ 5

Эта проблема отсутствует не только с источниками данных SQL, но и с источниками данных объекта. Тем не менее, при динамическом настройке DataSource в коде, когда это происходит плохо. К сожалению, MSDN иногда очень плохо разбирается в информации. Простое упоминание этого поведения (это не ошибка, а проблема дизайна) сэкономит много времени. Во всяком случае, я не очень склонен использовать для этого переменные сеанса. Обычно я сохраняю направление сортировки в ViewState.

Ответ 6

То, как я это делал, похоже на код, предоставленный принятым ответом, бит немного отличается, поэтому я подумал, что я тоже его поместил. Обратите внимание, что эта сортировка выполняется с DataTable, прежде чем она привязана к GridView.DataSource.

Вариант один: использование ViewState

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

Вариант второй: использование сеанса

Обратите внимание, что для устаревших целей предусмотрено следующее: если вы видите это в поле или что вы по-прежнему поддерживаете системы компаний, ориентированные на старые браузеры.

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

Ответ 7

Я не знаю, почему все забывают об использовании скрытых полей! Они настолько "дешевле", что ViewState (который я отключил с 2005 года). Если вы не хотите использовать Session или ViewState, то вот мое решение:

Поместите эти два скрытых поля на вашу страницу aspx и поместите сортировку по умолчанию для ваших данных (например, я использую LastName):

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

Затем поместите этот вспомогательный код на свою базовую страницу (у вас есть базовая страница, не так ли? Если нет, введите код .cs позади).

/// <summary>
/// Since native ASP.Net GridViews do not provide accurate SortDirections, 
/// we must save a hidden field with previous sort Direction and Expression.
/// Put these two hidden fields on page and call this method in grid sorting event
/// </summary>
/// <param name="hfSortExpression">The hidden field on page that has the PREVIOUS column that is sorted on</param>
/// <param name="hfSortDirection">The hidden field on page that has the PREVIOUS sort direction</param>
protected SortDirection GetSortDirection(GridViewSortEventArgs e, HiddenField hfSortExpression, HiddenField hfSortDirection)
{
    //assume Ascending always by default!!
    SortDirection sortDirection = SortDirection.Ascending;

    //see what previous column (if any) was sorted on
    string previousSortExpression = hfSortExpression.Value;
    //see what previous sort direction was used
    SortDirection previousSortDirection = !string.IsNullOrEmpty(hfSortDirection.Value) ? ((SortDirection)Enum.Parse(typeof(SortDirection), hfSortDirection.Value)) : SortDirection.Ascending;

    //check if we are now sorting on same column
    if (e.SortExpression == previousSortExpression)
    {
        //check if previous direction was ascending
        if (previousSortDirection == SortDirection.Ascending)
        {
            //since column name matches but direction doesn't, 
            sortDirection = SortDirection.Descending;
        }
    }

    // save them back so you know for next time
    hfSortExpression.Value = e.SortExpression;
    hfSortDirection.Value = sortDirection.ToString();

    return sortDirection;
}

Затем вам нужно обработать сортировку в обработчике событий сортировки сетки. Вызовите метод выше из обработчика событий сортировки, прежде чем вызывать свой основной метод, который получает ваши данные.

protected void gridContacts_Sorting(object sender, GridViewSortEventArgs e)
{
    //get the sort direction (since GridView sortDirection is not implemented!)
    SortDirection sortDirection = GetSortDirection(e, hfSortExpression, hfSortDirection);

    //get data, sort and rebind (obviously, this is my own method... you must replace with your own)
    GetCases(_accountId, e.SortExpression, sortDirection);
}

Поскольку так много примеров используют DataTables или DataViews или другие коллекции, отличные от LINQ, я думал, что включу пример вызова метода среднего уровня, который возвращает общий список, и используйте LINQ для сортировки по порядку округлить пример и сделать его более "реальным миром":

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

Наконец, вот сортировка вниз и грязная, использующая LINQ в общем списке пользовательских объектов. Я уверен, что есть что-то более увлекательное, что будет делать трюк, но это иллюстрирует концепцию:

закрытый статический список Сортировка (строка sortExpression, SortDirection sortDirection, список pendingCases)   {

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

И последнее, но не менее важное (я уже это сказал?), вы можете захотеть добавить что-то подобное в свой обработчик Page_Load, так что сетка связывается по умолчанию при загрузке страницы... Обратите внимание, что _accountId - это параметр querystring, преобразованный к собственному типу AccountID моего в этом случае...

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

Ответ 8

Все ответы не совсем корректны. Я использую To:

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

в gridView_Sorting...

Ответ 9

Еще один:) Не нужно писать имена столбцов жесткого кода.

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 затем:

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

Ответ 10

Это можно сделать без использования состояния просмотра или сеанса. Текущий порядок может быть определен на основе значения в первой и последней строке в столбце, который мы сортируем по:

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

Ответ 11

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

Ответ 12

Вероятно, это будет париться здесь, но решение, с которым я столкнулся, отлично подходит для моей ситуации:

Событие загрузки формы выглядит следующим образом:

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

Добавьте на страницу два скрытых поля:

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

Добавьте в свой asp объект: GridView:

AllowSorting="True" OnSorting="GridView1_Sorting"

Используйте следующее сортировочное событие GridView

protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
    if (lastSortExpression.Value == e.SortExpression.ToString())
    {
        if (lastSortDirection.Value == SortDirection.Ascending.ToString())
        {
            e.SortDirection = SortDirection.Descending;
        }
        else
        {
            e.SortDirection = SortDirection.Ascending;
        }
        lastSortDirection.Value = e.SortDirection.ToString();
        lastSortExpression.Value = e.SortExpression;
    }
    else
    {
        lastSortExpression.Value = e.SortExpression;
        e.SortDirection = SortDirection.Ascending;
        lastSortDirection.Value = e.SortDirection.ToString();
    }

    DataView dv = DataTable1.DefaultView;
    if (e.SortDirection == SortDirection.Ascending)
    {
        dv.Sort = e.SortExpression;
    }
    else
    {
        dv.Sort = e.SortExpression + " DESC";
    }

    DataTable1 = dv.ToTable();
    GridView1.DataSource = DataTable1.DefaultView;
    GridView1.DataBind();
}

Теперь каждый столбец в моем gridview сортируется без каких-либо дальнейших изменений, если какой-либо из столбцов изменяется.

Ответ 13

Прошло некоторое время с тех пор, как я использовал GridView, но я думаю, вам нужно установить свойство SortDirection сетки на все, что в настоящее время находится перед тем, как оставить метод OnSorting.

Так....

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

Ответ 14

Мне надоело разбираться с этой проблемой и поместить сортировку и сортировку столбца в ViewState....

Ответ 15

Чтобы переключиться на восходящий и нисходящий, я использую метод в моем приложении BasePage для кэширования выражения сортировки и направления сортировки:

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

SortExpression и SortDirection - оба свойства в BasePage, которые хранят и извлекают их значения из ViewState.

Итак, все мои производные страницы просто вызывают SetPageSort из метода сортировки GridView и связывают GridView:

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

BindGrid проверяет SortExpression и использует его и SortDirection для выполнения ORDERY BY в источнике данных сетки, примерно так:

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

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

Таким образом, базовый класс SetPageSort удаляет большую часть сложности сортировки GridView. Я чувствую, что что-то забываю, но это общая идея.

Ответ 16

XML:

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

код:

private string ConvertSortDirectionToSql(String sortExpression,SortDirection sortDireciton)
{
    switch (sortExpression)
    {
        case "DealCRMID":
             ViewState["DealCRMID"]=ChangeSortDirection(ViewState["DealCRMID"].ToString());
             return ViewState["DealCRMID"].ToString();

        case "DealCustomerName":
             ViewState["DealCustomerName"] = ChangeSortDirection(ViewState["DealCustomerName"].ToString());
             return ViewState["DealCustomerName"].ToString();

        case "SLCode":
             ViewState["SLCode"] = ChangeSortDirection(ViewState["SLCode"].ToString());
             return ViewState["SLCode"].ToString();

        default:
            return "ASC";
    }       
}

private string ChangeSortDirection(string sortDireciton)
{
    switch (sortDireciton)
    {
        case "DESC":
            return "ASC";
        case "ASC":
            return "DESC";
        default:
            return "ASC";
    }
}

protected void gvPendingApprovals_Sorting(object sender, GridViewSortEventArgs e)
{
    DataSet ds = (System.Data.DataSet)(gvPendingApprovals.DataSource);

    if(ds.Tables.Count>0)
    {
        DataView m_DataView = new DataView(ds.Tables[0]);
        m_DataView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql   (e.SortExpression.ToString(), e.SortDirection);

        gvPendingApprovals.DataSource = m_DataView;
        gvPendingApprovals.DataBind();
    }
}

Ответ 17

Это еще один способ решения проблемы:

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

Ответ 18

Старая строка, но, может быть, мой ответ поможет кому-то.

Сначала получите свой SqlDataSource как DataView:

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

    grid1.DataSourceID = Nothing
    grid1.DataSource = dataView
    grid1.DataBind()

End Sub

Затем используйте метод расширения для сортировки (вид выстрела, но хороший старт):

public static class DataViewExtensions
{
    public static string FieldSortDirection(this DataView dataView, HttpSessionState session, string sortExpression)
    {
        const string SORT_DIRECTION = "SortDirection";
        var identifier = SORT_DIRECTION + sortExpression;

        if (session[identifier] != null)
        {
            if ((string) session[identifier] == " ASC")
                session[identifier] = " DESC";
            else if ((string) session[identifier] == " DESC")
                session[identifier] = " ASC";
        }
        else
            session[identifier] = " ASC";

        return (string) session[identifier];
    }
}

Ответ 19

Использование решения SecretSquirrel выше

вот мой полный рабочий, производственный код. Просто измените dgvCoaches на имя вида сетки.

... при связывании сетки

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

и теперь сортировка

protected void gridView_Sorting(object sender, GridViewSortEventArgs e)
{
    DataTable dt = ViewState["AllCoaches"] as DataTable;

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

        dgvCoaches.DataSource = dt;
        dgvCoaches.DataBind();
    }
}

и вот код aspx:

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

Ответ 20

У меня была ужасная проблема с этим, поэтому я, наконец, прибегнул к использованию LINQ, чтобы заказать DataTable, прежде чем назначать ему представление:

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

В частности, я действительно нашел методы DataView.Sort и DataGrid.Sort ненадежными при сортировке логического поля.

Я надеюсь, что это поможет кому-то там.

Ответ 21

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

Ответ 22

Возможно, это поможет кому-то. Не уверен, что это потому, что это 2014 или я не понимаю проблему, которую этот пост пытается решить, но это очень просто с помощью slickgrid следующим образом:

Кажется, проблема заключается в том, как "запомнить", что такое текущий параметр сортировки, поэтому предложения касаются Asp.Net, поддерживающего это значение для вас. Однако slickGrid может рассказать вам, что такое текущий порядок сортировки:

Чтобы переключить сортировку по возрастанию, вы можете использовать grid.getSortColumns(), чтобы узнать, что такое сортировка столбцов. Это то, что я сделал, но я сортирую только по 1 столбцу за один раз, поэтому могу с уверенностью сделать это: if (grid.getSortColumns() [0].sortAsc) '

... так что мой код, который работает, выглядит так:

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

.. загрузите свои данные, как обычно, затем часть сортировки:

   // Clicking on a column header fires this event. Here we toggle the sort direction
    grid.onHeaderClick.subscribe(function(e, args) {
        var columnID = args.column.id;

        if (grid.getSortColumns()[0].sortAsc) {
            grid.setSortColumn(args.column.id, true);
        }
        else {
            grid.setSortColumn(args.column.id, false);
        }
    });

    // The actual sort function is like this 
        grid.onSort.subscribe(function (e, args) {
            sortdir = args.sortAsc ? 1 : -1;
            sortcol = args.sortCol.field;

            //alert('in sort');

            // using native sort with comparer
            // preferred method but can be very slow in IE with huge datasets
            dataView.sort(comparer, args.sortAsc);
            grid.invalidateAllRows();
            grid.render();
        });

// Default comparer is enough for what I'm doing here ..
function comparer(a, b) {
    var x = a[sortcol], y = b[sortcol];
    return (x == y ? 0 : (x > y ? 1 : -1));
}

Наконец, убедитесь, что у вас есть папка изображений SlickGrid, включенная на ваш сайт, и вы получите стрелки asc/desc, появляющиеся в столбце, когда вы его выберете. Если они отсутствуют, текст будет курсивом, но стрелки не появятся.

Ответ 23

Написал это, он работает для меня:

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

Ответ 24

Вот как я это делаю. Гораздо проще, чем многие ответы здесь ИМО:

Создайте этот класс SortDirection

    // ==================================================
    // SortByDirection
    // ==================================================
    public SortDirection SortByDirection
    {
        get
        {
            if (ViewState["SortByDirection"] == null)
            {
                ViewState["SortByDirection"] = SortDirection.Ascending;
            }

            return (SortDirection)Enum.Parse(typeof(SortDirection), ViewState["SortByDirection"].ToString());
        }
        set { ViewState["SortByDirection"] = value; }
    }

А затем используйте его в своей функции сортировки следующим образом:

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

Ответ 25

protected void gv_Sorting(object sender, GridViewSortEventArgs e)
{
    DataTable dataTable = (DataTable)Cache["GridData"];

    if (dataTable != null)
    {
        DataView dataView = new DataView(dataTable);
        string Field1 = e.SortExpression;
        string whichWay = "ASC";
        if (HttpContext.Current.Session[Field1] != null)
        {
            whichWay = HttpContext.Current.Session[Field1].ToString();
            if (whichWay == "ASC")
                whichWay = "DESC";
            else
                whichWay = "ASC";               
        }

        HttpContext.Current.Session[Field1] = whichWay;
        dataView.Sort = Field1 + " " + whichWay;      
        gv.DataSource = dataView;
        gv.DataBind();
    }
}

и вы сохраняете информацию, которая была ранее получена

    string SqlConn = ConfigurationManager.ConnectionStrings["Sql28"].ConnectionString;
    SqlConnection sqlcon = new SqlConnection(SqlConn);
    sqlcon.Open();

    SqlCommand cmd = new SqlCommand();
    cmd.Connection = sqlcon;
    cmd.CommandType = System.Data.CommandType.Text;
    cmd.CommandText = HttpContext.Current.Session["sql"].ToString();

    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    DataTable employees = new DataTable();
    adapter.Fill(employees);

    gv.DataSource = employees;
    gv.DataBind();

    Cache.Insert("GridData", employees, null, System.Web.Caching.Cache.NoAbsoluteExpiration,new TimeSpan(0, 360000, 0));

Ответ 26

В vb.net, но очень просто!

Protected Sub grTicketHistory_Sorting(sender As Object, e As GridViewSortEventArgs) Handles grTicketHistory.Sorting

    Dim dt As DataTable = Session("historytable")
    If Session("SortDirection" & e.SortExpression) = "ASC" Then
        Session("SortDirection" & e.SortExpression) = "DESC"
    Else
        Session("SortDirection" & e.SortExpression) = "ASC"
    End If
    dt.DefaultView.Sort = e.SortExpression & " " & Session("SortDirection" & e.SortExpression)
    grTicketHistory.DataSource = dt
    grTicketHistory.DataBind()

End Sub