Search code examples
c#asp.netgridview

Getting the DateRange in .aspx and .aspx.cs files


I'm trying to build on both front-end and back-end a date-range display such that when a user selects between two dates, it filters information between those two points. So far, I am having issues with just the first portion of the front end and managed to come up with this based on some examples I saw online

    <details>
        <div class="row">
            <div class="col-auto">
                <asp:Repeater ID="rFilterDateStarts" RunAt="Server">
                    <ItemTemplate>
                        <label class="form-label">Date From:</label>
                        <asp:TextBox AutoPostBack="true" ClientIDMode="Static" ID="txtDateStart" RunAt="Server" TextMode="Date" />
                        <button type="button" class="btn btn-outline-secondary badge rounded-pill text-body-emphasis"><%# Eval("created_date", "{0:yyyy-MM-dd}") %></button>
                    </ItemTemplate>
                </asp:Repeater>
            </div>

        <div class="col-auto">
            <asp:Repeater ID="rFilterDateEnds" RunAt="Server">
                <ItemTemplate>
                    <label class="form-label">Date To:</label>
                    <asp:TextBox AutoPostBack="true" ClientIDMode="Static" ID="txtDateEnds" RunAt="Server" TextMode="Date" />
                    <button type="button" class="btn btn-outline-secondary badge rounded-pill text-body-emphasis"><%# Eval("created_date", "{0:yyyy-MM-dd}") %></button>
                </ItemTemplate>
            </asp:Repeater>
        </div>
    </div>
</details>

I am very new to C# and want to know if this is correct or I'm going about things in the wrong direction.

I tried to follow the examples for the C# and SQl from the block codes I found online.

<div class='container'>
    <div class="row">
        From:<asp:TextBox ID="txtFromDate" runat="server" class="form-control date-input" ReadOnly="true" />
    </div>
    <div class="row">
        To:<asp:TextBox ID="txtToDate" runat="server" class="form-control date-input" ReadOnly="true" />
    </div>
    <hr />
    <asp:GridView ID="gvEmployees" runat="server" AutoGenerateColumns="false" CssClass="table table-responsive table-bordered">
        <Columns>
            <asp:BoundField DataField="Id" HeaderText="Id" />
            <asp:BoundField DataField="Name" HeaderText="Name" />
            <asp:BoundField DataField="OrderDate" HeaderText="Date" DataFormatString="{0:dd/MMM/yyyy}" />
        </Columns>
    </asp:GridView>
    <br />
    <asp:Button Text="Filter" runat="server" OnClick="OnFilter" />
</div>

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        gvEmployees.DataSource = GetData("", "");
        gvEmployees.DataBind();
    }
}

protected void OnFilter(object sender, EventArgs e)
{
    DateTime fromDate = Convert.ToDateTime(txtFromDate.Text);
    DateTime toDate = Convert.ToDateTime(txtToDate.Text);
    gvEmployees.DataSource = GetData(fromDate.ToString(), toDate.ToString());
    gvEmployees.DataBind();
}

private DataTable GetData(string fromDate, string toDate)
{
    string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    SqlCommand cmd = new SqlCommand();
    string query = "SELECT * FROM Employees";
    if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate))
    {
        query += "WHERE OrderDate BETWEEN @From AND @To";
        cmd.Parameters.AddWithValue("@From", fromDate);
        cmd.Parameters.AddWithValue("@To", toDate);
    }
    using (SqlConnection con = new SqlConnection(conString))
    {
        using (SqlDataAdapter sda = new SqlDataAdapter())
        {
            cmd.Connection = con;
            cmd.CommandText = query;
            sda.SelectCommand = cmd;
            using (DataTable dt = new DataTable())
            {
                sda.Fill(dt);
                return dt;
            }
        }
    }
}

Solution

  • Not at all clear why you have some introduction of a repeater. I suggest you dump that.

    Drop in 2 textboxes (with TextMode = date, and that will give you a date picker without any extra efforts on your part).

    After the 2 textboxes (and our search button), then just add your GridView.

    Hence, this markup:

            <h3>Search Hotel Bookings</h3>
    
            <div style="float: left">
                <h4>Enter start date</h4>
                <asp:TextBox ID="txtStartDate" runat="server"
                    TextMode="Date">
                </asp:TextBox>
            </div>
    
            <div style="float: left; margin-left: 30px">
                <h4>Enter start date</h4>
                <asp:TextBox ID="txtEndDate" runat="server"
                    TextMode="Date">
                </asp:TextBox>
            </div>
            <asp:Button ID="cmdSearch" runat="server"
                Style="float: left; margin-left: 30px; margin-top: 20px"
                Text="Search Bookings"
                CssClass="btn"
                OnClick="cmdSearch_Click" />
    
            <%--        Start a new line--%>
    
            <div style="clear: both; height: 10px"></div>
    
            <asp:GridView ID="GridView1" runat="server"
                CssClass="table table-hover"
                Width="50%"
                AutoGenerateColumns="False" DataKeyNames="ID">
                <Columns>
                    <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
                    <asp:BoundField DataField="LastName" HeaderText="LastName" />
                    <asp:BoundField DataField="City" HeaderText="City" />
                    <asp:BoundField DataField="HotelName" HeaderText="Hotel" />
                    <asp:BoundField DataField="Description" HeaderText="Description" />
                    <asp:BoundField DataField="BookingDate"
                        HeaderText="Booking Date" DataFormatString="{0:d}"
                        ItemStyle-Width="110px" />
                </Columns>
            </asp:GridView>
    

    And our code behind can be this:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // optinal load all of grid on first page load
                LoadGrid();
            }
        }
    
        void LoadGrid()
        {
            string strSQL =
                "SELECT * FROM tblHotelsA ";
    
            SqlCommand cmdSQL = new SqlCommand(strSQL); 
            if (txtStartDate.Text.Trim().Length > 0 
                & txtStartDate.Text.Trim().Length > 0 )
            {
                cmdSQL.CommandText += "WHERE BookingDate BETWEEN @Start AND @End ";
                cmdSQL.Parameters.Add("@Start", SqlDbType.Date).Value = txtStartDate.Text;
                cmdSQL.Parameters.Add("@End", SqlDbType.Date).Value = txtEndDate.Text;
            }
            cmdSQL.CommandText += "ORDER BY BookingDate ";
            GridView1.DataSource = MyRstP(cmdSQL);
            GridView1.DataBind();
        }
    
        protected void cmdSearch_Click(object sender, EventArgs e)
        {
            LoadGrid();
    
        }
    
        public DataTable MyRstP(SqlCommand cmdSQL)
        {
            DataTable rstData = new DataTable();
            using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
            {
                using (cmdSQL)
                {
                    cmdSQL.Connection = conn;
                    conn.Open();
                    rstData.Load(cmdSQL.ExecuteReader());
                }
            }
            return rstData;
        }
    

    In fact, I suggest moving the MyRstP "helper" routing to a global static class, as then you not have to write such code over and over.

    The end result is thus:

    First, we select the start and end date:

    enter image description here

    Then we hit the search button

    enter image description here

    Edit: additional using directives

    My using directives were:

    using System;
    using System.Data;
    using System.Data.SqlClient;
    

    So, nothing beyond what a typical page with SQL queries would require.