asp.net - que - Clasificación GridView: SortDirection siempre Ascending
sort column gridview asp net (24)
Tengo una vista en cuadrícula y necesito ordenar sus elementos cuando el usuario hace clic en el encabezado.
Su fuente de datos es un objeto List.
El aspx se define de esta manera:
<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>
El código detrás se define de esta manera:
Primera carga:
protected void btnSearch_Click(object sender, EventArgs e)
{
List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
this.grdHeader.DataSource = items;
this.grdHeader.DataBind();
}
cuando el usuario hace clic en los encabezados:
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();
}
Mi problema es que e.SortDirection siempre se establece en Ascendente.
Tengo una página web con un código similar y funciona bien, e.SortDirection alterna entre Ascendente y Descendente.
Qué hice mal ?
¡No sé por qué todos olvidan usar campos ocultos! Son mucho más "baratos" que ViewState (que he apagado desde 2005). Si no desea usar Session o ViewState, esta es mi solución:
Coloque estos dos campos ocultos en su página aspx y coloque la clasificación predeterminada que desea para sus datos (estoy usando LastName por ejemplo):
<asp:HiddenField ID="hfSortExpression" runat="server" Value="LastName" />
<asp:HiddenField ID="hfSortDirection" runat="server" Value="Ascending" />
Luego coloque este código auxiliar en su página Base (usted tiene una página base, ¿no?) Si no, ingrese su código .cs detrás).
/// <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;
}
A continuación, debe gestionar la ordenación en su controlador de eventos de clasificación de cuadrícula. Llame al método anterior desde el controlador de eventos de clasificación, antes de llamar a su método principal que obtiene sus datos
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);
}
Como hay tantos ejemplos que usan DataTables o DataViews u otras colecciones que no son LINQ friendly, pensé incluir un ejemplo de una llamada a un método de nivel medio que devuelve una lista genérica, y usar LINQ para hacer la clasificación con el fin de completar el ejemplo y hacerlo más "mundo real":
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();
}
Por último, aquí está la clasificación descendente y sucia utilizando LINQ en una lista genérica de objetos personalizados. Estoy seguro de que hay algo más fantástico que hará el truco, pero esto ilustra el concepto:
static static Sort Sort (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;
}
Por último, pero no menos importante (¿ya dije eso?) Es posible que desee poner algo como esto en su controlador Page_Load, de modo que la cuadrícula se enlace por defecto al cargar la página ... Tenga en cuenta que _accountId es un parámetro querystring, convertido a una costumbre tipo de AccountID propio en este caso ...
if (!Page.IsPostBack)
{
//sort by LastName ascending by default
GetCases(_accountId,hfSortExpression.Value,SortDirection.Ascending);
}
Cadena vieja, pero tal vez mi respuesta ayudará a alguien.
Primero, obtenga su SqlDataSource como 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
A continuación, utilice un método de extensión para el género (tipo de foto de chivo, pero un buen comienzo):
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];
}
}
El problema con Session y Viewstate es que también debe realizar un seguimiento del control gridview para el que se almacena SortColumn y Direction si hay más de una vista de cuadrícula en la página.
Una alternativa a Session y Viewstate es agregar 2 atributos a Gridview y realizar un seguimiento de la columna y la dirección de esa manera.
Aquí hay un ejemplo:
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");
}
}
Esta es otra forma de resolver el problema:
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();
}
Este problema está ausente no solo con las fuentes de datos SQL sino también con las fuentes de datos de objeto. Sin embargo, al configurar DataSource dinámicamente en el código, es cuando esto sale mal. Desafortunadamente, MSDN a veces es muy pobre en información. Una simple mención de este comportamiento (esto no es un error sino un problema de diseño) ahorraría mucho tiempo. De todos modos, no estoy muy dispuesto a usar variables de Sesión para esto. Por lo general, almaceno la dirección de clasificación en un ViewState.
Ha pasado un tiempo desde que utilicé GridView, pero creo que es necesario establecer la propiedad SortDirection de la grilla en lo que sea actualmente antes de abandonar el método OnSorting.
Asi que....
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();
La forma en que hice esto es similar al código que me brindó la respuesta aceptada , pero es un poco diferente, así que pensé que podría publicarlo también. Tenga en cuenta que esta ordenación se realiza en una DataTable antes de que se vincule con la GridView .DataSource.
Opción uno: usar 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;
}
Opción dos: usar la sesión
Tenga en cuenta que se proporciona lo siguiente para fines heredados en el caso de que lo vea en el campo, o que aún respalda sistemas de la compañía que se dirigen a navegadores más antiguos.
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;
}
La ordenación bidireccional automática solo funciona con la fuente de datos SQL. Desafortunadamente, toda la documentación en MSDN supone que está utilizando eso, por lo que GridView puede ser un poco frustrante.
La forma en que lo hago es hacer un seguimiento del pedido por mi cuenta. Por ejemplo:
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();
}
Me cansé de lidiar con este problema y puse la dirección de ordenación y columna de clasificación en ViewState ....
Otro :) No es necesario codificar los nombres de las columnas.
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 entonces:
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;
}
Para alternar entre ascendente y descendente, utilizo un método en la página base de mi aplicación para almacenar en caché la expresión de clasificación y la dirección de clasificación:
protected void SetPageSort(GridViewSortEventArgs e)
{
if (e.SortExpression == SortExpression)
{
if (SortDirection == "ASC")
{
SortDirection = "DESC";
}
else
{
SortDirection = "ASC";
}
}
else
{
SortDirection = "ASC";
SortExpression = e.SortExpression;
}
}
SortExpression y SortDirection son propiedades en BasePage que almacenan y recuperan sus valores de ViewState.
Entonces, todas mis páginas derivadas solo llaman a SetPageSort desde el método de ordenamiento de GridView y vinculan a GridView:
protected void gv_Sorting(object sender, GridViewSortEventArgs e)
{
SetPageSort(e);
BindGrid();
}
BindGrid comprueba SortExpression y lo utiliza y SortDirection para hacer un ORDER BY en el origen de datos de la cuadrícula, algo como esto:
if (SortExpression.Length > 0)
{
qry.ORDER_BY(SortExpression + " " + SortDirection);
}
gv.DataSource = qry.ExecuteReader();
gv.DataBind();
Por lo tanto, la clase base ''SetPageSort elimina gran parte del trabajo pesado de la ordenación GridView. Siento que me estoy olvidando de algo, pero esa es la idea general.
Probablemente apueste aquí, pero la solución que se me ocurrió es la que funciona mejor para mi situación:
El evento de carga de formulario se ve así:
private DataTable DataTable1;
protected void Page_Load(object sender, EventArgs e)
{
DataTable1 = GetDataFromDatabase();
this.GridView1.DataSource = DataTable1.DefaultView;
this.GridView1.DataBind();
}
Agregue dos campos ocultos a la página:
<asp:HiddenField runat="server" ID="lastSortDirection" />
<asp:HiddenField runat="server" ID="lastSortExpression" />
Agregue lo siguiente a su asp: Objeto GridView:
AllowSorting="True" OnSorting="GridView1_Sorting"
Utilice el siguiente evento de ordenación 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();
}
Ahora, cada columna de mi vista de cuadrícula se ordena sin necesidad de cambios adicionales si alguna de las columnas cambia.
Puede usar una variable de sesión para almacenar la última expresión de clasificación y cuando clasifique la cuadrícula la próxima vez compare la expresión de clasificación de la cuadrícula con la variable de sesión que almacena la última expresión de clasificación. Si las columnas son iguales, verifique la dirección de la clasificación anterior y ordene en la dirección opuesta.
Ejemplo:
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";
}
Quizás esto ayudará a alguien. No estoy seguro de si es porque es 2014 o no entiendo el problema que esta publicación intenta resolver, pero esto es muy simple con slickgrid de la siguiente manera:
El problema parece ser cómo "recordar" cuál es la configuración de clasificación actual, por lo que las sugerencias se basan en que Asp.Net tenga ese valor para usted. Sin embargo, slickGrid puede decirle cuál es el orden de clasificación actual:
Para alternar sort asc desc, puede usar grid.getSortColumns () para averiguar cuál es la clasificación de columna actualmente. Esto es lo que hice, pero solo estoy ordenando en 1 columna a la vez, así puedo hacer esto de manera segura: ''if (grid.getSortColumns () [0] .sortAsc)''
... así que mi código que funciona es así:
// 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 }, ];
.. carga tus datos como siempre, luego la parte de ordenación:
// Clicking on a column header fires this event. Here we toggle the sort direction
grid.onHeaderClick.subscribe(function(e, args) {
var columnID = args.column.id;
if (grid.getSortColumns()[0].sortAsc) {
grid.setSortColumn(args.column.id, true);
}
else {
grid.setSortColumn(args.column.id, false);
}
});
// The actual sort function is like this
grid.onSort.subscribe(function (e, args) {
sortdir = args.sortAsc ? 1 : -1;
sortcol = args.sortCol.field;
//alert(''in sort'');
// using native sort with comparer
// preferred method but can be very slow in IE with huge datasets
dataView.sort(comparer, args.sortAsc);
grid.invalidateAllRows();
grid.render();
});
// Default comparer is enough for what I''m doing here ..
function comparer(a, b) {
var x = a[sortcol], y = b[sortcol];
return (x == y ? 0 : (x > y ? 1 : -1));
}
Lastly make sure you have the SlickGrid image folder included in your site and you''ll get the asc/desc arrows appearing on the column when you select it. If they are missing the text will go italics but no arrows will appear.
Se puede hacer sin el uso de View State o Session. El orden actual se puede determinar según el valor en la primera y la última fila de la columna que ordenamos:
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();
}
Toda esa respuesta no es del todo correcta. Yo uso eso:
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);
en gridView_Sorting ...
Tuve un problema horrible con esto, así que finalmente recurrí al uso de LINQ para ordenar el DataTable antes de asignarlo a la vista:
Dim lquery = From s In listToMap
Select s
Order By s.ACCT_Active Descending, s.ACCT_Name
En particular, encontré que los métodos DataView.Sort y DataGrid.Sort no son confiables al ordenar un campo booleano.
Espero que esto ayude a alguien por ahí.
Una solución simple:
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;
}
Al igual que la clasificación predeterminada GridView y ligero en el ViewState.
USO:
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();
}
Usando la solución de SecretSquirrel arriba
aquí está mi código de producción completo. Simplemente cambie dgvCoaches a su nombre de vista de cuadrícula.
... durante la unión de la grilla
dgvCoaches.DataSource = dsCoaches.Tables[0];
ViewState["AllCoaches"] = dsCoaches.Tables[0];
dgvCoaches.DataBind();
y ahora la clasificación
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();
}
}
y aquí está el código 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>
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"/>
Código:
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();
}
}
In vb.net but very simple!
Protected Sub grTicketHistory_Sorting(sender As Object, e As GridViewSortEventArgs) Handles grTicketHistory.Sorting
Dim dt As DataTable = Session("historytable")
If Session("SortDirection" & e.SortExpression) = "ASC" Then
Session("SortDirection" & e.SortExpression) = "DESC"
Else
Session("SortDirection" & e.SortExpression) = "ASC"
End If
dt.DefaultView.Sort = e.SortExpression & " " & Session("SortDirection" & e.SortExpression)
grTicketHistory.DataSource = dt
grTicketHistory.DataBind()
End Sub
Wrote this, it works for me:
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
if (ViewState["sortExpression"] == null || ViewState["sortExpression"].ToString() != e.SortExpression.ToString())
MyDataTable.DefaultView.Sort = e.SortExpression + " ASC";
else
{
if (ViewState["SortDirection"].ToString() == "Ascending")
MyDataTable.DefaultView.Sort = e.SortExpression = e.SortExpression + " DESC";
else
MyDataTable.DefaultView.Sort = e.SortExpression + " ASC";
}
GridView1.DataSource = MyDataTable;
GridView1.DataBind();
ViewState["sortExpression"] = e.SortExpression;
ViewState["SortDirection"] = e.SortDirection;
}
<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;
}
}
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();
}