Lucas Araujo
Lucas Araujo

Reputation: 143

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

Upvotes: 2

Views: 1785

Answers (2)

Dr. Stitch
Dr. Stitch

Reputation: 918

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

Upvotes: 3

Rahul Nikate
Rahul Nikate

Reputation: 6337

The exception means that you are performing some operation on the News class that requires that it be serialized, but it doesn't have an attribute marking it as serializable.

Make sure all the fields are serializable types, and then attach the Serializable attribute to your class:

[Serializable]     
public class News
{

}

Upvotes: 0

Related Questions