Не знаю, почему все забывают об использовании скрытых полей! Они намного «дешевле», чем 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, 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;
}
И последнее, но не менее важное (я уже говорил?), Вы можете захотеть поместить что-то подобное в ваш обработчик Page_Load, чтобы сетка связывалась по умолчанию при загрузке страницы ... Обратите внимание, что _accountId - это параметр строки запроса, преобразованный на мой собственный тип AccountID в этом случае ...
if (!Page.IsPostBack)
{
//sort by LastName ascending by default
GetCases(_accountId,hfSortExpression.Value,SortDirection.Ascending);
}