当前位置:  开发笔记 > 后端 > 正文

GridView排序:SortDirection总是升序

如何解决《GridView排序:SortDirection总是升序》经验,为你挑选了7个好方法。

我有一个gridview,我需要在用户点击标题时对其元素进行排序.
它的数据源是一个List对象.

aspx以这种方式定义:


    
        
        
        
    

后面的代码是这样定义的:
首先加载:

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

当用户点击标题时:

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

我的问题是e.SortDirection始终设置为Ascending.
我有一个类似代码的网页,它运作良好,e.SortDirection在升序和降序之间交替.

我做错了什么 ?



1> 小智..:

Session和Viewstate的问题在于,如果页面上有多个gridview,您还必须跟踪存储SortColumn和Direction的gridview控件.

Session和Viewstate的替代方法是向Gridview添加2个属性,并以这种方式跟踪Column和Direction.

这是一个例子:

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

}


我喜欢你的属性替代viewstate.

2> 小智..:

您可以使用会话变量来存储最新的排序表达式,并在下次对网格进行排序时将网格的排序表达式与存储最后一个排序表达式的Session变量进行比较.如果列相等,则检查先前排序的方向并按相反方向排序.

例:

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


实际上 - 上面的代码是*错误*并且如果在不同的浏览器选项卡中同时查看两个网格将会中断.用ViewState替换Session.

3> maxbeaudoin..:

简单的解决方案:

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

非常类似于ViewState上的默认GridView排序和轻量级.

用法:

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

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



4> Sander..:

自动双向排序仅适用于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有时候信息非常糟糕.简单地提一下这种行为(这不是错误,而是设计问题)可以节省大量时间.无论如何,我不太倾向于使用Session变量.我通常将排序方向存储在ViewState中.



6> rjzii..:

我这样做的方式类似于接受的答案提供的代码,位有点不同所以我想我也会把它放在那里.请注意,在将DataTable绑定到GridView .DataSource 之前,正在对DataTable进行此排序.

选项一:使用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!会话中断跨浏览器选项卡功能.

7> AdamE..:

我不知道为什么每个人都忘记使用隐藏的字段!它们比ViewState(我自2005年以来关闭)"便宜"得多.如果您不想使用Session或ViewState,那么这是我的解决方案:

将这两个隐藏字段放在您的aspx页面上,并为您的数据设置所需的默认排序(例如我使用LastName):



然后把这个帮助代码放在你的Base页面中(你有一个基页不是吗?如果没有,请将你的.cs代码放在后面).

/// 
/// 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
/// 
/// The hidden field on page that has the PREVIOUS column that is sorted on
/// The hidden field on page that has the PREVIOUS sort direction
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;
}

接下来,您需要在网格排序事件处理程序中处理排序.在调用获取数据的main方法之前,从排序事件处理程序调用上面的方法

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 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进行的向下和脏排序.我确信那里会有更好的东西可以解决问题,但这说明了这个概念:

private static List 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;
}

最后但并非最不重要(我已经说过了吗?)你可能想在你的Page_Load处理程序中添加这样的东西,以便网格在页面加载时默认绑定...注意_accountId是一个查询字符串参数,转换为自定义在这种情况下我自己的AccountID类型......

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

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有