简体   繁体   中英

Date columns will not sort on Gridview filled from DataTable

I am using this example to sort GridView loaded from DataTable. I also reviewed this post - I used sajanyamaha advice by adding columns to DataTable and that's when GridView's date columns starting sorting properly with one peculiarity. I have 11 columns, first column is a selectcommand that redirects to another page. I have no boundfields or template fields, gridview is filled from datatable in code behind.

The problem is sorting and paging work fine on all columns EXCEPT the 2 Date columns. The Date columns, ReviewDue and SubmittedDate. They sort correctly but they do not retain the sort order while paging. GridView will reset to page 1 at each sort column change which causes the user to never see past page 1 when Date column is sorted. The issue I am trying to resolve and understand is why do all the other columns function correctly but the Date columns behave differently? What custom handling is needed to get date columns to behave like the other string or int columns?

I have googled plenty but I don't find anything with this oddity.

Here is my pertinent code.

    protected void Page_Load(object sender, EventArgs e)
        { 
            if (!IsPostBack)
            {
                ViewState["SortExpr"] = "EPRID";
                ViewState["SortDir"] = " DESC";

                if (blnIsAdmin == true || blnIsManager == true)
                {
                    BindData(); 
                }
                else
                {
                    //redirect
                    Response.Redirect("~/ErrorPages/AccessDenied.aspx");
                }
            }
        }


        private void BindData()
        { 
                GridView1.DataSource = this.GetData();
                GridView1.DataBind();

        }

        private DataTable GetData() 
        {
            string cmdStr = "SELECT * FROM ….ORDER BY " + ViewState["SortExpr"].ToString() + " " + ViewState["SortDir"].ToString();

            DataTable table = new DataTable();
            table.Columns.Add("EPRID", typeof(Int32));
            table.Columns.Add("FormName", typeof(String));
            table.Columns.Add("Name", typeof(String));
            table.Columns.Add("Completed", typeof(Boolean));
            table.Columns.Add("Sup1", typeof(String));
            table.Columns.Add("Sup2", typeof(String));
            table.Columns.Add("Sup3", typeof(String));
            table.Columns.Add("ReviewDue", typeof(DateTime));
            table.Columns.Add("SubmittedDate", typeof(DateTime));
            table.Columns.Add("SubmittedBy", typeof(String));
            table.Columns.Add("DocID", typeof(Int32));

            using (SqlConnection conn = new SqlConnection(conStr))
            {
                using (SqlCommand cmd = new SqlCommand(cmdStr, conn))
                {
                    cmd.CommandType = CommandType.Text;

                    //get all EPRs (unfiltered grid)
                    if (blnIsAdmin == true ")
                    {
                        cmdStr = "SELECT * FROM … ORDER BY " + ViewState["SortExpr"].ToString() + " " + ViewState["SortDir"].ToString();
                        using (SqlDataAdapter da = new SqlDataAdapter(cmdStr, conn))
                        {  
                            da.Fill(table);
                        } 
                    }
                    else if (blnIsManager == true)
                    {
                        cmdStr = "SELECT * FROM… WHERE user = @user …ORDER BY " + ViewState["SortExpr"].ToString() + " " + ViewState["SortDir"].ToString(); 

                        using (SqlDataAdapter da = new SqlDataAdapter(cmdStr, conn))
                        {
                            da.SelectCommand.Parameters.Add(new SqlParameter { ParameterName = "@user", Value = strCurrentUser, SqlDbType = SqlDbType.VarChar, Size = 50 });
                            da.Fill(table);
                        }
                    } 
                }
            }
            return table;
        }
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
        {
            //go to page 1 when sorting
            GridView1.PageIndex = 0;

            string sortExpression = e.SortExpression;

                if (GridViewSortDirection == SortDirection.Ascending)
                {
                    GridViewSortDirection = SortDirection.Descending;
                    SortGridView(sortExpression, DESCENDING);
                    ViewState["SortDir"] = " DESC";
                }
                else
                {
                    GridViewSortDirection = SortDirection.Ascending;
                    SortGridView(sortExpression, ASCENDING);
                    ViewState["SortDir"] = " ASC";
                }

            ViewState["SortExpr"] = sortExpression; 
        }
private void SortGridView(string sortExpression, string direction)
        {   
            ViewState["SortExpr"] = sortExpression; 
            ViewState["SortDir"] = direction;

                //get unfiltered grid
                DataTable dt = GetData();    
                DataView dv = new DataView(dt); 

                dv.Sort = sortExpression + direction;

                GridView1.DataSource = dv;

                GridView1.DataBind(); 
        }  
        public SortDirection GridViewSortDirection
        { 
            get
            { 
                if (ViewState["sortDirection"] == null) 
                    //ViewState["sortDirection"] = SortDirection.Ascending;
                ViewState["sortDirection"] = SortDirection.Descending; 
                return (SortDirection)ViewState["sortDirection"]; 
            } 
            set { ViewState["sortDirection"] = value; } 
        } 

        protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {    
            GridView1.PageIndex = e.NewPageIndex; 
            BindData();  
        }
<asp:GridView ID="GridView1" runat="server" 
            onselectedindexchanged="GridView1_SelectedIndexChanged" 
            AllowPaging="True" 
            AllowSorting="True" 
            Caption="List of awaiting or completed employee performance reviews" 
            PageSize="25" 
            onsorting="GridView1_Sorting" 
            onpageindexchanging="GridView1_PageIndexChanging" 
            CellPadding="4" 
            DataKeyNames="EPRID,DocID" 
            ForeColor="#333333" GridLines="None" 
            onrowcommand="GridView1_RowCommand" 
            onrowdatabound="GridView1_RowDataBound" 
            onselectedindexchanging="GridView1_SelectedIndexChanging" 
        CssClass="GridStyle"  >
            <RowStyle BackColor="#F7F6F3" ForeColor="Black" />
            <Columns>
                <asp:CommandField ShowSelectButton="True"  />  
            </Columns>
            <FooterStyle Font-Bold="True" ForeColor="Black" />
            <PagerStyle  ForeColor="Black" HorizontalAlign="Center" />
            <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
            <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="Black" />
            <EditRowStyle BackColor="#999999" />
            <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
        </asp:GridView>

Solved! Part of the issue was with the SELECT statement in the view that was used in Sql query strings' FROM clause, cmdStr (details of this were left out of my original question for brevity-possibly my first error in getting proper help?). In the views' SELECT statement, the 2 datetime columns were constructed like this:

,Convert(varchar(10),NextReview,112) as ReviewDue
,Convert(varchar(10),SubmittedDate,112) as SubmittedDate 

and should have been simply:

,NextReview as ReviewDue
,SubmittedDate
,etc...

(BTW it made no differnce which standard I used, 101, 110, 111, 112...). Also the corresponding data types in the DataTable's Add() method should match as DateTime in GetData() . Finally I added a condition and modified the ORDER BY clause in the SQL inline query, cmdStr to:

//pass ViewState to variable for use in cmdStr when DateTime columns are sorted on
    strExpression = ViewState["SortExpr"].ToString();

        if (strExpression == "ReviewDue" || strExpression == "SubmittedDate")
            {
             cmdStr = "SELECT * FROM vwView ORDER BY CONVERT(DATE, " + strExpression + ", 120) " + ViewState["SortDir"].ToString();  
            } 

        else
        {
        //use original cmdStr
        }

In the gridviews _RowDataBound() event I also formated the date to show Date part only in the grid like this:

//ReviewDue will never be null
        e.Row.Cells[8].Text = Convert.ToDateTime(((DataRowView)e.Row.DataItem)["ReviewDue"]).ToString("d");

                //SubmittedDate can be null, handle null 
                object dtmDate9 = ((DataRowView)e.Row.DataItem)["SubmittedDate"];

                if (dtmDate9 == DBNull.Value)
                {
                    e.Row.Cells[9].Text = String.Empty;
                }
                else
                {

                    e.Row.Cells[9].Text = Convert.ToDateTime(((DataRowView)e.Row.DataItem)["SubmittedDate"]).ToString("d");
                }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM