Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort a list of objects in a GridView in asp.net?

I have a list of objects

List<News> theNews = controlClass.ListNews();

ListNews() is loaded with News objects from a dataset.

then I have a gridview

    <asp:GridView ID="gvNews" runat="server" AutoGenerateColumns="False"  OnSelectedIndexChanged="gvNews_SelectedIndexChanged" AllowSorting="True" OnSorting="gvNews_Sorted">
        <Columns>
            <asp:BoundField DataField="titNew" HeaderText="Title" />
            <asp:BoundField DataField="dateNew" HeaderText="Date" SortExpression="dateNew" />
            <asp:BoundField DataField="typeNew" HeaderText="Type" />
            <asp:CommandField SelectText="See More" ShowSelectButton="True" />
        </Columns>
    </asp:GridView>

I store said list into this GridView and then I have the following code to Sort it

    private void LoadNews()
    {
        this.gvNews.DataSource = controlClass.ListNews();
        this.gvNews.DataBind();
        ViewState["dt"] = controlClass.ListNews();
        ViewState["sort"] = "Asc";
    }

    protected void gvNews_Sorted(object sender, GridViewSortEventArgs e)
    {
        DataTable result = (DataTable)ViewState["dt"];
        if (result.Rows.Count>0)
        {
            if(ViewState["sort"].ToString()=="Asc")
            {
                result.DefaultView.Sort = e.SortExpression + " Desc";
                ViewState["sort"] = "Desc";
            }
            else
            {
                result.DefaultView.Sort = e.SortExpression + " Asc";
                ViewState["sort"] = "Asc";
            }
            gvNews.DataSource = result;
            gvNews.DataBind();
        }
    }

Yet this leads me to the following error: Type 'MySolution.News' in Assembly 'MySolution, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. I can't seem to store my list in a ViewState, is there a way around this?

UPDATE: I've made my News Class Serializable but I get the following error when I click the Date header in the gridview

Unable to cast object of type 'System.Collections.Generic.List`1[MySolution.News]' to type 'System.Data.DataTable'.

UPDATE NUMBER 2: I modified my gvNews_Sorted Method to match with @Dr.Stitch 's Answer.

protected void gvNews_Sorted(object sender, GridViewSortEventArgs e)
{
   List<News>result = (List<News>)ViewState["dt"];
   if (result.Count>0)
   {
      if(ViewState["sort"].ToString()=="Asc")
      {
        result = result.OrderBy(e.SortExpression + " Desc").ToList();
        ViewState["sort"] = "Desc";
      }
      else
      {
         result = result.OrderBy(e.SortExpression + " Asc").ToList();
         ViewState["sort"] = "Asc";
      }

      gvNews.DataSource = result;
      gvNews.DataBind();
   }
}

and I'm getting the following error in the line

result = result.OrderBy(e.SortExpression + " Desc").ToList();

enter image description here

UPDATE 3: I made further changes trying Dr Stitch's new answer, now despite no longer crashing it fails to do nothing at all, when I click the header nothing changes

like image 571
Lucas Araujo Avatar asked Jun 27 '16 07:06

Lucas Araujo


1 Answers

You're saving a List<News> object

ViewState["dt"] = controlClass.ListNews();

But trying to retrieve a DataTable object

DataTable result = (DataTable)ViewState["dt"];

You have to change your gvNews_Sorted to this:

protected void gvNews_Sorted(object sender, GridViewSortEventArgs e)
{
   List<News>result = (List<News>)ViewState["dt"];
   if (result.Count>0)
   {
      if(ViewState["sort"].ToString()=="Asc")
      {
        if ("titNew" == e.SortExpression)
            result = result.OrderByDescending(r => r.titNew).ToList();
        //...do it to all the fields

        ViewState["sort"] = "Desc";
      }
      else
      {
        if ("titNew" == e.SortExpression)
            result = result.OrderBy(r => r.titNew).ToList();
        //...do it to all the fields
         ViewState["sort"] = "Asc";
      }

      gvNews.DataSource = result;
      gvNews.DataBind();
      ViewState["dt"] = result;
   }
}

Make sure the LoadNews() only calls on non-postback event

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
     LoadNews();
  }
}
like image 190
Dr. Stitch Avatar answered Nov 13 '22 22:11

Dr. Stitch