Monday, May 26, 2014

ASP.NET Gridview sorting that bound to a List<> of custom objects as DataSource

In AsP.NET, Gridview with List<> of custom objects as DataSource does not support sorting. Here is a code to achieve it. Here the sort direction and Sort column is stored in a ViewState. So when we click a column name to sort it will check the previous sort direction from the ViewState["SortDirection"] and ViewState["SortColumn"]. If the previous direction is ASC means it will do DESC sort vice versa. I have used LINQ to sort the List. The sorting is done inside the GridView Rowcommand event with the help of CommandName and CommandArgument as parameter. And also you have to change the Gridview header from Label to LinkButton in the Header Template as it will make postbacks. Check out the code you can learn some new C# techniques as i have learned when i tried to implement this functionalities. Design Code:

<asp:GridView ID="grdManageUsers" runat="server" AutoGenerateColumns="False" OnRowCommand="grdManageUsers_RowCommand">
    <Columns>
        <asp:TemplateField HeaderText="First Name">
            <HeaderTemplate>
                <asp:LinkButton ID="lnkFirstname" runat="server" CommandName="Sort" CommandArgument="Firstname">First Name</asp:LinkButton>
            </HeaderTemplate>
            <ItemTemplate>
                <asp:Label ID="lblFirstNameEdit" runat="server" Text='<%# Eval("Firstname")%>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtFirstname" runat="Server" Text='<%# Eval("Firstname") %>'></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Last Name">
            <HeaderTemplate>
                <asp:LinkButton ID="lnklastname" runat="server" CommandName="Sort" CommandArgument="Lastname">Last Name</asp:LinkButton>
            </HeaderTemplate>
            <ItemTemplate>
                <asp:Label ID="lblLastnameEdit" runat="server" Text='<%# Eval("Lastname")%>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtLastname" runat="Server" Text='<%# Eval("Lastname") %>'></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Email">
            <HeaderTemplate>
                <asp:LinkButton ID="lnkEmail" runat="server" CommandName="Sort" CommandArgument="Email">Email</asp:LinkButton>
            </HeaderTemplate>
            <ItemTemplate>
                <asp:Label ID="lblEmailEdit" runat="server" Text='<%# Eval("Email")%>'></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtEmail" runat="Server" Text='<%# Eval("Email") %>'></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        </Columns>
    </asp:GridView>

Code behind C#:

List userList = new List();

private SortDirection LastSortDirection
{
    get
    {
        return (ViewState["LastSortDirection"] == null) ? SortDirection.Descending : (SortDirection)ViewState["LastSortDirection"];
    }
    set
    {
        ViewState["LastSortDirection"] = value;
    }
}

private string LastSortColumn
{
    get
    {
        return (ViewState["LastSortColumn"] == null) ? "Firstname" : (string)ViewState["LastSortColumn"];
    }
    set
    {
        ViewState["LastSortColumn"] = value;
    }
}
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        try
        {
           userList = GetUsers(); // It will return the List of users from data source.
           ViewState["USERLIST"] = userList; // It can be used for sorting
        }
        catch (Exception ex)
        {
           
        }
    }
}
protected void grdManageUsers_RowCommand(object sender, GridViewCommandEventArgs e)
{
    try
    {
        if (e.CommandName == "Sort" && !string.IsNullOrEmpty(e.CommandArgument.ToString()))
        {
            userList = ViewState["USERLIST"] as List;
            if (userList != null && userList.Count > 0)
            {
                IQueryable query = userList.AsQueryable();
                string newSortColumn = string.Empty;
                SortDirection newSortDirection = SortDirection.Descending;
                BindGridView(Sort(query, e.CommandArgument.ToString(), LastSortColumn, LastSortDirection, out newSortColumn, out newSortDirection));
                LastSortColumn = newSortColumn;
                LastSortDirection = newSortDirection;
            }
        }
    }
    catch (Exception ex)
    {      
    }
}
private void BindGridView(List users)
{
     grdManageUsers.DataSource = users;
     grdManageUsers.DataBind();
}
public List Sort(IQueryable list, string sortColumn, string lastSortColumn, SortDirection lastSortDirection, out string newSortColumn, out SortDirection newSortDirection)
{
    newSortColumn = string.Empty;
    newSortDirection = SortDirection.Descending;
    var result = new List();
    try
    {
        if (sortColumn == lastSortColumn)
        {
            newSortColumn = sortColumn;
            if (lastSortDirection == SortDirection.Ascending)
            {
                newSortDirection = SortDirection.Descending;
                result = SortProcess(list, SortDirection.Descending, sortColumn);
            }
            else
            {
                newSortDirection = SortDirection.Ascending;
                result = SortProcess(list, SortDirection.Ascending, sortColumn);
            }
        }
        else
        {
            newSortColumn = sortColumn;
            newSortDirection = SortDirection.Ascending;
            result = SortProcess(list, SortDirection.Ascending, sortColumn);
        }
    }
    catch
    {
        throw;
    }
    return result;
}
public List SortProcess(IQueryable list, SortDirection sortDirection, string sortColumn)
{
    IQueryable query = list.AsQueryable();
    try
    {
        var pi = typeof(T).GetProperty(sortColumn);

        if (sortDirection == SortDirection.Ascending)
        {
            query = query.OrderBy(x => pi.GetValue(x, null));
        }
        else
        {
            query = query.OrderByDescending(x => pi.GetValue(x, null));
        }
    }
    catch
    {
        throw;
    }
    return query.ToList();
}