日期列不会对从 DataTable 填充的 Gridview 进行排序

Date columns will not sort on Gridview filled from DataTable

我正在使用 this example to sort GridView loaded from DataTable. I also reviewed this post - 我通过向 DataTable 添加列来使用 sajanyamaha 建议,那时 GridView 的日期列开始以一种特性正确排序。我有 11 列,第一列是一个重定向到另一个页面的选择命令。我没有边界字段或模板字段,gridview 是从代码后面的数据表中填充的。

问题是除 2 个日期列外,所有列的排序和分页工作正常。日期列、ReviewDue 和 SubmittedDate。它们排序正确,但在分页时不保留排序顺序。 GridView 将在每次排序列更改时重置为第 1 页,这会导致用户在对 Date 列进行排序时永远不会看到过去的第 1 页。我试图解决和理解的问题是为什么所有其他列都能正常运行但日期列的行为不同?需要什么自定义处理才能使日期列的行为与其他字符串或 int 列相似?

我在谷歌上搜索了很多,但我没有找到任何与此奇怪的东西。

这是我的相关代码。

    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>

已解决!部分问题出在 Sql 查询字符串的 FROM 子句 cmdStr 中使用的视图中的 SELECT 语句(为简洁起见,我的原始问题中没有详细说明 -可能是我在获得适当帮助时的第一个错误?)。在视图的 SELECT 语句中,2 个日期时间列的构造如下:

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

应该很简单:

,NextReview as ReviewDue
,SubmittedDate
,etc...

(顺便说一句,我使用的标准没有区别,101、110、111、112 ...)。此外,DataTable 的 Add() 方法中相应的数据类型应与 DateTime 中的 GetData() 相匹配。最后我添加了一个条件并修改了 SQL 内联查询中的 ORDER BY 子句, cmdStr 为:

//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
        }

在 gridviews _RowDataBound() 事件中,我还格式化了日期以仅在网格中显示日期部分,如下所示:

//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");
                }