Управления GridView сортировка: направления сортировки по возрастанию всегда
у меня есть GridView и мне нужно отсортировать его элементы, когда пользователь нажимает на заголовок.
Его источником данных является объект списка.
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 всегда устанавливается в возрастание.
У меня есть веб-страница с аналогичным кодом, и он хорошо работает, E. SortDirection чередуется между восходящим и нисходящим.
что я сделал не так ?
24 ответа:
вы можете использовать переменную сеанса для хранения последнего выражения сортировки и при сортировке сетки в следующий раз сравнить выражение сортировки сетки с переменной сеанса, которая хранит последнее выражение сортировки. Если столбцы равны, то проверьте направление предыдущей сортировки и сортировки в обратном направлении.
пример:
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"; }
проблема с Session и Viewstate заключается в том, что вы также должны отслеживать элемент управления gridview, для которого хранится SortColumn и направление, если на странице есть более одного 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"); } }
простое решение:
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(); }
автоматическая двунаправленная сортировка работает только с источником данных 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(); }
эта проблема отсутствует не только в источниках данных SQL, но и в источниках данных объектов. Однако при установке источника данных динамически в коде, вот когда это идет плохо. К сожалению, MSDN иногда действительно очень плохо справляется с информацией. Простое упоминание этого поведения (это не ошибка, а проблема дизайна) сэкономит много времени. Во всяком случае, я не очень склонен использовать переменные сеанса для этого. Я обычно храню направление сортировки в ViewState.
то, как я это сделал, похоже на код, который принято отвечать при условии, бит немного отличается, поэтому я подумал, что я бы поставил его там, а также. Обратите внимание, что эта сортировка выполняется для DataTable прежде чем он будет привязан к GridView.Источник данных.
Вариант Первый: Использование 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; }
Я не знаю, почему все забывают об использовании скрытых полей! Они настолько "дешевле", чем ViewState (который я отключил с 2005 года). Если вы не хотите использовать Session или ViewState, то вот мое решение:
поместите эти два скрытых поля на страницу aspx и поместите сортировку по умолчанию, которую вы хотите для своих данных (например, я использую LastName):
<asp:HiddenField ID="hfSortExpression" runat="server" Value="LastName" /> <asp:HiddenField ID="hfSortDirection" runat="server" Value="Ascending" />
затем поместите этот вспомогательный код на свою базовую страницу (у вас есть базовая страница, не так ли? Если нет, то положите в свой .цезий с фоновым кодом.)
/// <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); }
так как многие примеры там использовать объект DataTable или в разделе Объекты DataView или другие номера для 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, направления сортировки направления сортировки, список 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); }
все, что ответ не полностью правильный. Я использую это:
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...
еще один :) не нужно жестко кодировать имена столбцов..
DataTable dt = GetData(); SortDirection sd; string f; GridViewSortDirection(gvProductBreakdown, e, out sd, out f); dt.DefaultView.Sort = sd == SortDirection.Ascending ? f + " asc" : f + " desc"; gvProductBreakdown.DataSource = dt; gvProductBreakdown.DataBind();
а еще:
private void GridViewSortDirection(GridView g, GridViewSortEventArgs e, out SortDirection d, out string f) { f = e.SortExpression; d = e.SortDirection; if (g.Attributes[f] != null) { d = g.Attributes[f] == "ASC" ? SortDirection.Descending : SortDirection.Ascending; g.Attributes[f] = d == SortDirection.Ascending ? "ASC" : "DESC"; } else { g.Attributes[f] = "ASC"; d = SortDirection.Ascending; }
Это можно сделать без использования состояния представления или сеанса. Текущий порядок может быть определен на основе значения в первой и последней строке в столбце, который мы сортируем:
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(); }
<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; } }
прошло некоторое время с тех пор, как я использовал 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();
Я устал от решения этой проблемы и поставил направление сортировки и столбец сортировки в ViewState....
для переключения по возрастанию и убыванию я использую метод в базовой странице моего приложения для кэширования выражения сортировки и направления сортировки:
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, чтобы сделать порядок в источнике данных сетки, что-то вроде этого:
if (SortExpression.Length > 0) { qry.ORDER_BY(SortExpression + " " + SortDirection); } gv.DataSource = qry.ExecuteReader(); gv.DataBind();
Итак, базовый класс' SetPageSort удаляет большую часть тяжелой работы сортировки GridView. Мне кажется, что я что-то забыл, но это общая идея.
это, вероятно, будет держать пари похоронен здесь, но решение, которое я придумал, который отлично подходит для моей ситуации:
событие загрузки формы выглядит так:
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 сортируется без необходимости каких-либо дальнейших изменений, если какой-либо из столбцы меняются.
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(); } }
Это еще один способ решения вопроса:
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(); }
старая строка, но может мой ответ поможет кому-то.
сначала получите свой 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]; } }
используя 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>
У меня была ужасная проблема с этим, поэтому я, наконец, прибегнул к использованию LINQ для заказа DataTable перед назначением его представлению:
Dim lquery = From s In listToMap Select s Order By s.ACCT_Active Descending, s.ACCT_Name
в частности, я действительно нашел DataView.Сортировка и Датагрид.Методы сортировки ненадежны при сортировке логического поля.
Я надеюсь, что это поможет кому-то там.
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(); }
возможно, это кому-то поможет. Не уверен, что это потому, что это 2014 или я не понимаю проблему, которую этот пост пытается решить, но это очень просто с slickgrid следующим образом:
проблема, похоже, заключается в том, как "помнить", что текущая настройка сортировки так Предложения вокруг Asp.Net держа это значение для вас. Однако slickGrid может сказать вам, что текущий порядок сортировки:
для переключения сортировки asc desc вы можете использовать сетку.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, появляющиеся в столбце при его выборе. Если они отсутствуют текст будет выделен курсивом, но стрелки не появятся.
писал это, это работает для меня:
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 но очень просто!
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