Friday 9 August 2013

How to perform sorting on Gridview bound to generic list collection

Let's say we have a list or collection based on some entity class and the underlying data is bound to the grid.

Following code performs sorting operation on such kind of grid whose data source is collection.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
             CellPadding="4" 
            EnableModelValidation="True" ForeColor="#333333" GridLines="None" 
            AllowSorting="True" 
            onsorting="GridView1_Sorting">
            <AlternatingRowStyle BackColor="White" />
            <EmptyDataTemplate><h2>No Data Found</h2></EmptyDataTemplate>
            <Columns>           
                <asp:TemplateField HeaderText="ProductId" SortExpression="ProductId">
                    <ItemTemplate>
                        <asp:Label ID="lblEmpNo" runat="server" Text='<%# Eval("ProductId") %>' />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="ProducName" SortExpression="ProductName">
                    <ItemTemplate>
                        <asp:Label ID="lblEmpNo" runat="server" Text='<%# Eval("ProductName") %>' />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
            <EditRowStyle BackColor="#2461BF" />
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
            <RowStyle BackColor="#EFF3FB" />
            <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
        </asp:GridView>

Now create a function like this which returns list of products.
 private List<Products> GetProducts()    //Products is class with two properties ProductId & ProductName
        {
            List<Products> lst = new List<Products>();
            lst.Add(new Products { ProductId = 11, ProductName = "Samsung" });
            lst.Add(new Products { ProductId = 12, ProductName = "nokia" });
            lst.Add(new Products { ProductId = 14, ProductName = "Whirepool" });
            lst.Add(new Products { ProductId = 22, ProductName = "pupil" });
            lst.Add(new Products { ProductId = 31, ProductName = "softtech" });
            return lst;

        }

 protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
        {
            List<Products> lstcoll = GetProducts();
            lstcoll.Sort(new GenericComparer<Products>(e.SortExpression, GridViewSortDirection));
            GridView1.DataSource = lstcoll;
            GridView1.DataBind();
        }
        public SortDirection GridViewSortDirection
        {
            get
            {                            
                if (ViewState["sortDirection"] == null)
                    ViewState["sortDirection"] = SortDirection.Ascending;
                else
                {
                    if (((SortDirection)ViewState["sortDirection"]) == SortDirection.Ascending)
                    {
                        ViewState["sortDirection"] = SortDirection.Descending;
                    }
                    else
                    {
                        ViewState["sortDirection"] = SortDirection.Ascending;
                    }
                }
                return (SortDirection)ViewState["sortDirection"];
            }
            set
            {
                ViewState["sortDirection"] = value;
            }
        }

Now implement the GenericComparer where constructor takes sortexpression and sortdirection inputs.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;


public class GenericComparer<T> : IComparer<T>
{
    private SortDirection sortDirection;
    public SortDirection SortDirection
    {
        get { return this.sortDirection; }
        set { this.sortDirection = value; }
    }

    private string sortExpression;
    public GenericComparer(string sortExpression, SortDirection sortDirection)
    {
        this.sortExpression = sortExpression;
        this.sortDirection = sortDirection;
    }

    public int Compare(T x, T y)
    {
        PropertyInfo propertyInfo = typeof(T).GetProperty(sortExpression);
        IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
        IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);
        if (SortDirection == SortDirection.Ascending)
        {
            return obj1.CompareTo(obj2);
        }
        else return obj2.CompareTo(obj1);
    }


}