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;
}
}
}
}
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:
Then we hit the search button
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.