Using HTML5 Date Input Type Inside GridView
HTML5 provides several new input types such as email, URL and Date. While using Date input type
a textbox is displayed as a date-picker by browsers such as Chrome and Opera.
Such a textbox uses dates in yyyy-MM-dd format (ISO format) and this formatting
can lead to some problems as discussed below.
Consider, for example, the Employees table from Northwind database. It has two date columns BirthDate and HireDate. Let's assume that you wish to display these columns in a GridView so that the user can change these two date values. To make the data entry easy you decide to use HTML5 date input type. A BoundField of a GridView always uses a plain TextBox (type = "text") to use HTML5 date input type you need to add a TemplateField to the GridView. The EditItemTemplate of this TemplateField should have a TextBox whose TextMode property is set to Date. This will cause the GridView to render a TextBox of type Date.
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("BirthDate") %>' TextMode="Date"></asp:TextBox>
</EditItemTemplate>
The above markup shows the EditItemTemplate of the BirthDate column. Now,
when you run the web form and click on the Edit button, the BirthDate and
HireDate columns will be displayed as date-pickers but the date will not be
populated in them by default. This is shown in the following figure:
As you can see in spite of binding BirthDate and HireDate columns to the
respective database columns the date-picker doesn't show the existing date in
the controls. The reason for this odd behavior is that the date input type needs
date in ISO format (yyyy-MM-dd) if it has to display it correctly. By default
the .NET dates are MM/dd/yyyy and hence the date-picker fails to show them
correctly. Additionally, if the user accidently hits Update button while the
date-pickers weren't having anything selected NULL values will be added to the
columns (if null values are allowed for those field). This undue side effect is
shown in the following figure.
How to rectify this problem? If you are using some data source control such
as SQL Data Source control you can get rid of this behavior by setting the Date
format in the databinding expression. Have a look at the following markup:
<EditItemTemplate>
<asp:TextBox ... Text='<%# Bind("BirthDate","{0:yyyy-MM-dd}") %>' TextMode="Date"></asp:TextBox>
</EditItemTemplate>
As you can see the second parameter of Bind() is now set to {0:yyyy-MM-dd}
this way the value of the TextBox will be set in the ISO date format and now the
date-picker will display it correctly.
Alternatively, you can also use RowDataBound event handler to convert date
values from MM/dd/yyyy to yyyy-MM-dd and then assign to the textboxes. The
following code shows how:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (GridView1.EditIndex == e.Row.RowIndex)
{
TextBox t1 = (TextBox)e.Row.FindControl("TextBox1");
TextBox t2 = (TextBox)e.Row.FindControl("TextBox2");
DateTime dt1, dt2;
if (DateTime.TryParse(t1.Text, out dt1))
{
t1.Text = dt1.ToString("yyyy-MM-dd");
}
if (DateTime.TryParse(t2.Text, out dt2))
{
t2.Text = dt2.ToString("yyyy-MM-dd");
}
}
}
}
The RowDataBound event is raised for each and every row when the GridView is
being databound. The above code checks whether the row being bound is editable
or not. This is done using EditIndex property of the GridView. It then retrieves
the values from BirthDate and HireDate textboxes (TextBox1 and TextBox2
respectively). This value will be in MM/dd/yyyy format. The code then parses
these values into DateTime variables and then assigns them back to the textboxes
in yyyy-MM-dd format.
If you are not using any data source control or model binding for databinding
purpose, you may need to handle the date conversion during update operation
also. This can be done in the RowUpdating event handler as shown below:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//BirthDate
DateTime dt1 = DateTime.ParseExact(e.NewValues[2].ToString(), "yyyy-MM-dd",
System.Globalization.CultureInfo.CurrentCulture,
System.Globalization.DateTimeStyles.None);
//HireDate
DateTime dt2 = DateTime.ParseExact(e.NewValues[3].ToString(), "yyyy-MM-dd",
System.Globalization.CultureInfo.CurrentCulture,
System.Globalization.DateTimeStyles.None);
// Now update data with dt1 and dt2
}
The RowUpdating event is raised before updating a row. The above code
retrieves dates selected by the end user using e.NewValues collection. These
values will be in yyyy-MM-dd format since they are being submitted from the
date-picker. You can then parse them into DateTime variables for the sake of
updating them in the database.