GridView sorting & paging

2019-02-11 08:03发布

问题:

I would like to display simple gridview on my page and provide sorting and paging functionality to it. Sorting and paging individually is working ok, but the combination of both does not. For example if I sort the first column descending and then go to page number two, then I see the second page of data with default sorting (ascending).

I relied heavily on the code from this question: GridView sorting: SortDirection always Ascending, but the problem remains. Also - as it seems I have to change my code so that instead of Session object ViewState is used, have to figure this out also...

My code, simplified, with only two columns:

aspx:

<asp:GridView ID="dgvView" runat="server" AutoGenerateColumns="false" AllowPaging="true"
    PageSize="10" AllowSorting="True" OnPageIndexChanging="DgvViewPageIndexChanging" OnSorting="OnSort">
    <Columns>
        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name">
            <ItemStyle />
        </asp:BoundField>
        <asp:BoundField DataField="BirthDate" HeaderText="Birth date" DataFormatString="{0:dd.MM.yyyy}"
            SortExpression="BirthDate">
            <ItemStyle />
        </asp:BoundField>
    </Columns>
</asp:GridView>

And codebehind:

public partial class TestPage :Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DisplayData();
        }
    }

    private void DisplayData()
    {
        Session["TableView"] = GetUsers();
        dgvView.DataSource = Session["TableView"];
        dgvView.DataBind();
    }

    protected void DgvViewPageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        dgvView.PageIndex = e.NewPageIndex;
        DisplayData();
    }

    private List<MyUser> GetUsers()
    {
        var users = new List<MyUser>();
        for (int i = 0; i < 100; i++)
        {
            users.Add(new MyUser("Name" + i.ToString().PadLeft(2, '0'), new DateTime(2000, 1, 1).AddDays(i)));
        }
        return users;
    }

    private class MyUser
    {
        public string Name { get; private set; }
        public DateTime BirthDate { get; private set; }

        public MyUser(string name, DateTime birthDate)
        {
            Name = name;
            BirthDate = birthDate;
        }
    }

    protected void OnSort(object sender, GridViewSortEventArgs e)
    {
        Func<MyUser, object> f;
        if (e.SortExpression == "Name") f = u => u.Name;
        else f = u => u.BirthDate;

        dgvView.DataSource = Sort((List<MyUser>)Session["TableView"], f, GetSortDirection(e.SortExpression));
        dgvView.DataBind();
    }

    private List<MyUser> Sort<T>(IEnumerable<MyUser> user, Func<MyUser, T> f, SortDirection sortDirection)
    {
        if (sortDirection == SortDirection.Ascending) return user.OrderBy(f).ToList();
        return user.OrderByDescending(f).ToList();
    }

    private SortDirection GetSortDirection(string column)
    {
        string sessionVariable = "TableSort" + column;
        SortDirection sortDirection;

        if (Session[sessionVariable] == null)
        {
            sortDirection = SortDirection.Ascending;
        }
        else if ((SortDirection)Session[sessionVariable] == SortDirection.Ascending)
        {
            sortDirection = SortDirection.Descending;
        }
        else
        {
            sortDirection = SortDirection.Ascending;
        }

        Session[sessionVariable] = sortDirection;
        return sortDirection;
    }
}

回答1:

You must use ViewState in order to persist your data

public string SortVariable
{
     get
     {
        if(ViewState["YourKey"] == null)
            return string.Empty;
        return (string)ViewState["YourKey"];
      }
     set 
     {
         ViewState["YourKey"] = value;
     }
}

With this solution when you change page, you get index sort in your viewstate before sort.

When you fire SortCommand you must set value of viewstate described

you don't need Session because you are in the same page, you don't navigate

 protected void OnSort(object sender, GridViewSortEventArgs e)
    {

        //Here you set your value SortVariable
        SortVariable = e.SortExpression;
        ...
    }

And in display data

you create dataview and sort treatment

private void DisplayData()
    {
            //GetSortVariable
            //before   bind with dataview you sort
    }


回答2:

The issue is on

protected void DgvViewPageIndexChanging(object sender, GridViewPageEventArgs e)
{
    dgvView.PageIndex = e.NewPageIndex;
    DisplayData();
}

You bind your grid with non-sorted brand new Data when you call the DisplayData() method.

Save you sorting parameters in the Viewstate (session is useless for this)

If you are using Asp.Net 4 why not using datatables or jQGrid?



回答3:

I solved it with the help of other two answers.

My solution:

public partial class TestPage1 : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ViewState["Data"] = MyUser.GetUsers();
            ViewState["SortExpression"] = "Name";
            DisplayData("Name", SortDirection.Ascending);
        }
    }

    private void DisplayData(string sortExpression, SortDirection sortDirection)
    {
        Func<MyUser, object> f;
        if (sortExpression == "Name") f = u => u.Name;
        else f = u => u.BirthDate;

        if (sortDirection == SortDirection.Ascending)
        {
            dgvView.DataSource = ((IEnumerable<MyUser>)ViewState["Data"]).OrderBy(f).ToList();
        }
        else
        {
            dgvView.DataSource = ((IEnumerable<MyUser>)ViewState["Data"]).OrderByDescending(f).ToList();
        }

        dgvView.DataBind();
    }

    protected void DgvViewPageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        dgvView.PageIndex = e.NewPageIndex;

        string sortExpression = ViewState["SortExpression"].ToString();
        DisplayData(sortExpression, GetDefaultSortDirection(sortExpression));
    }

    protected void OnSort(object sender, GridViewSortEventArgs e)
    {
        ViewState["SortExpression"] = e.SortExpression;
        ViewState[e.SortExpression] = GetReverseSortDirection(e.SortExpression);
        DisplayData(e.SortExpression, (SortDirection)ViewState[e.SortExpression]);
    }

    private SortDirection GetDefaultSortDirection(string sortExpression)
    {
        if (ViewState[sortExpression] == null)
        {
            ViewState[sortExpression] = SortDirection.Ascending;
        }

        return (SortDirection)ViewState[sortExpression];
    }

    private SortDirection GetReverseSortDirection(string sortExpression)
    {
        if (ViewState[sortExpression] == null)
        {
            ViewState[sortExpression] = SortDirection.Descending;
        }
        else
        {
            ViewState[sortExpression] = (SortDirection) ViewState[sortExpression] == SortDirection.Descending ? SortDirection.Ascending : SortDirection.Descending;
        }

        return (SortDirection)ViewState[sortExpression];
    }
}