asp.net gridview bind dateformat not working with update - asp.net

I have a GridView with a TemplateField column which shows a DateTime from a DataSource.
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:TemplateField HeaderText="Start Date">
<EditItemTemplate>
<asp:TextBox ID="txtDateStart" runat="server"
Text='<%# Bind("dtDateStart", "{0:dd/MM/yyyy}") %>'</asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("dtDateStart", "{0:dd/MM/yyyy}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
Displaying the date in the correct format works as it should. Note that the format starts with DAY followed by MONTH.
When I switch to edit mode, change the date in the TextBox to '31-01-2013' and press the GridView's update-link i get an error:
Cannot convert value of parameter 'dtDateStart' from 'System.String' to 'System.DateTime'
The error is generated by the GridView not my own code.
It happens before the UpdateMethod of my DataSource is called.
When i type '01-31-2012' the data is processed correctly and the value is updated into the database.
Somehow when the date is displayed it uses format dd-MM-yyyy (just as I need it to)
But when it reads the new value form the TextBox it uses MM-dd-yyyy
Can somebody please help me?

thanks for your reply.
I do not know about culture settings within the website. I was assuming that proving the Bind-function with a dateformat would be sufficient.
By now I have implemented the following workaround, which is hopefully useful for others:
I have added an additional property to my class which is of type string. This property I only use for binding to the gridview.
// Original Date property //
public DateTime dtDateStart { get; set; }
// Additional Date property of type string //
public string sDateStart
{
get
{
return dtDateStart.ToString("dd/MM/yyyy");
}
set
{
dtDateStart = DateTime.ParseExact(value, "dd/MM/yyyy", null);
}
}
I am not sure if this should be marked as the answer. But maybe others can use this as a quick workaround as well.

I think you can use like this
<EditItemTemplate>
<asp:TextBox ID="txtDateStart" runat="server"
Text='<%# Convert.ToDateTime(Bind("dtDateStart")).ToString("dd/MM/yyyy") %>'</asp:TextBox>
</EditItemTemplate>
this weill help you.

Related

In aspx-code, can we use Templatefield .HeaderText within validation control ErrorMessage?

In the aspx-code, I would like to reference the Templatefield HeaderText as a value in the validation-control's ErrorMessage, but do not know how. I want to reduce copy-paste errors.
I give an example of what I would like to code into the aspx-code.
<asp:TemplateField HeaderText="Last Name" SortExpression="cLASTNAME">
<EditItemTemplate>
<asp:TextBox ID="txtLastName" runat="server" Text='<%# Bind("cLASTNAME") %>' MaxLength="20" CssClass="ucIsRequired"></asp:TextBox>
<asp:RequiredFieldValidator ID="rqfvLastName" runat="server"
ControlToValidate="txtLastName"
ErrorMessage="'??HeaderText??**' value is required."
Display="none" ValidationGroup="valgrpDetails"
SetFocusOnError="False" Font-Size="Small"></asp:RequiredFieldValidator>
</EditItemTemplate>
...etc...
Please note the ??HeaderText?? in the ErrorMessage code. I would like the HeaderText ("Last Name") to be inserted where ??HeaderText?? is so that when the error-text is rendered the error-text would be: " 'Last Name' value is required. " (of course, without quotes).
Your comments and solutions with examples will be very welcome and helpful.
Of course, if there is a way to reference the Templatefield's HeaderText in the code-behind, please provide a sample snippet.
Thanks, in advance...John
A possible solution is to use a resource file, and then read its value when you need it and don't want to repeat the string.
Add the asp.net folder called App_GlobalResources to your website root, and add a new .resx file in it. Call it HeaderNames.resx.
Open that file, and add a row with: LastNameHeaderText as its name, and Last Name as its value.
Then, in your RequiredFieldValidator replace your ErrorMessage property with the following:
ErrorMessage = '<%# Resources.HeaderNames.LastNameHeaderText + " value is required." %>'
Finally, to use the same on your template header, add the following at your GridView (or whatever) Data Bound event:
protected void MyDataBound(object sender, EventArgs e)
{
((GridView)sender).Columns[1].HeaderText = Resources.HeaderNames.LastNameHeaderText;
}

Getting the bound type of templated column controls in gridView

Hi I have following grid view
<asp:GridView ID="grdSettings" runat="server" Height="400px" Width="100%"
AutoGenerateColumns="false" >
<Columns>
<asp:TemplateField HeaderText="XYZ" BoundFieldName="XYZTypeName">
<ItemTemplate>
<asp:Label ID="lblCustomerName" runat="server" Text='<%# Bind("CustomerName") %>'>
</asp:Label>
<asp:Label ID="lblCostumerId" runat="server" Text='<%#Bind("CustomerId") %>'></asp:Label>
</asp:TemplateField>
</Columns>
</asp:GridView>
Which is bound by List of Customer ,class is as follows
Class Customer
{
public string CustomerName { get; set; }
public int CustomerId { get; set; }
}
Now on a method named GetGridStuff() , i need to iterate in every column and get the type that was bound to controls in template field. For example in case of the first control in the template field
<asp:Label ID="lblCustomerName" runat="server" Text='<%# Bind("CustomerName") %>' >
</asp:Label>
I need to know what type of property data it contains , in this case its CustomerName. I need to get this dynamically at run time as to write code in part of program which is not aware if this grid structure. I have the grid object with me and i can access all properties.
Let me try this, being away from coding for more than 5 years now and if I understand the problem correctly as you may want to handle it through server side code.
Look for an event called ItemBound (or similar forgive me for my memory), this gives you values of all the items in current row (Properties). You also need to declare temp control types (label,textbox etc) and assign corresponding value to these controls using e.FindControl with appropriate type casting, e.g. Label l = (Label)e.Findcontrol("Name")
downside of the approach you should avoid too much of process as it is going to execute on every row creating of the grid.
Let me know if you still want a precise code to handle the problem but otherwise this description should at least help you to look for Row Level Event to crack the prob and also encourage you to stick to tech forums :)

C# - ASP.NET - Calendar Control - Specified cast is not valid

I have a gridview where I keep track of deadlines. I have 2 dates herefor. A expected date (date where the deadline is supposed to be completed) and an actual date (date where the deadline was completed). Now in my DB all the expected dates have values because they are meant to finish at around the same date each month. However the actual date is blank.
This gives me following error due to the null-values: Exception Details: System.InvalidCastException: Specified cast is not valid.
Now I found something while looking on the Internet and that is to call a helper method (see the selectedDate property - I copied to same value of selectedDate into VisibleDate, because else I had the same error) However this presents me with another error which is that I can't get the newly selected value!
<asp:TemplateField HeaderText="Actual Date" SortExpression="Actual_Date">
<EditItemTemplate>
<asp:Calendar ID="Calendar2" runat="server" VisibleDate='<%# Bind("Actual_Date") %>' SelectedDate='<%# FixNullDate(Eval("Actual_Date")) %>'></asp:Calendar>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("Actual_Date", "{0:d}") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
Here is my code of from my templatefield for the actual date
Please help, I'm kinda lost :p
You need to check for null:
<%# string.IsNullOrEmpty(Bind("Actual_Date").ToString()) ? "0000-00-00 00:00:00.000": Bind("Actual_Date").ToString() %>

casting problem of star rating?

I have an application with ajax star rating but when i am assigning value to CurrentRating from datatable then it showing error of "Specified cast is not valid".
I am using this code.
<asp:TemplateField HeaderText="Rating" SortExpression="CustomerRating">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "CustomerRating")%>'></asp:Label></a>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<cc1:Rating ID="Rating1" runat="server" CurrentRating='<%# Bind("CustomerRating") %>'
StarCssClass="ratingStar"
WaitingStarCssClass="savedRatingStar"
FilledStarCssClass="filledRatingStar"
EmptyStarCssClass="emptyRatingStar"
>
</cc1:Rating>
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</asp:TemplateField>
Then its showing error CurrentRating='<%# Bind("CustomerRating") %>'.
I am taking refrence from these sites.
asp.net forum
Code Project
Same thing working on Code project.
The problem is most likely that the CustomerRating property of your data item is not of the correct data type. Rating expects an int. The Databinder does use reflection and attempts to automatically handle type conversions, but it has limits.
Unfortunatly there isn't enough information in your qustion to know what the actual runtime type of CustomerRating is, so I can't say why it can't be cast. My advise would be to explicitly cast or convert the property like so:
CurrentRating='<%# (string)Bind("CustomerRating") %>'
CurrentRating='<%# Bind("CustomerRating").ToString() %>'
CurrentRating='<%# (int)Bind("CustomerRating") %>'
If you can't convert it simply, or just need to get a debugger on it so you can figure out what the type is you can call out to a custom method in your code-behind instead (and you can attach a debugger there to so you can see the runtime type of the item:
CurrentRating='<%# MyCustomMethod(Eval("CustomerRating")) %>'
in code behind:
public string MyCustomMethod(object customerRating)
{
string rValue = ... //do whatever you need to do to customerRating to get a string out of it
// good place to set a breakpoint you you can examine what type customerRating actually is so you can figure out how best to convert it to something databinding can use
return rValue;
}

How to modify Bind("MyValue") in asp.net

I'm having headache with Time values and multiple time zones.
I'm storing new DateTime values in UTC time, but I face problem when I try to modify them using LinqDataSource and GridView.
I can easily show correct time in
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# TimeManager.ToLocalTime((DateTime)Eval("OrderDate")) %>' />
</ItemTemplate>
Currently this will add 1 hour to UTC time stored in DB.
However, binding back to source is not easy. Bind("OrderDate") cannot be modified like TimeManager.ToGlobalTime((DateTime)Bind("OrderDate")).
I was thinking of using OnUpdating event of LinqDataSource to update value to global time, but what if user modified other fields and not date field? Every time he updates record time value would be smaller for one hour.
Comparing old and new values also is not great because user can modify date portion of datetime and not time, which is influenced by time zones?
If I had way to show local time in gridview's all states then I could easily use OnUpdating of LinqDataSource.
Please share your thoughts...
Have you considered making the change to your model? Let's assume that the name of the object you are binding to is CustomerOrder. You could add the following class to your project (in the same namespace as your Linq objects):
public partial class CustomerOrder
{
public DateTime LocalOrderDate
{
get { return TimeManager.ToLocalTime(OrderDate); }
set { OrderDate = TimeManager.ToUTCTime(value); }
}
}
Now instead of binding to OrderDate, bind to LocalOrderDate. This will automatically make the UTC / Local Time conversion to the OrderDate.
(Note: I'm assuming you have TimeManager.ToLocalTime() and TimeManager. ToUTCTime() properly defined)
The way I've handled this sort of thing in the past is to use Eval in the EditItemTemplate as well. Let the user edit the item in local time. Then add OnItemUpdating handler for the gridview and add extract the value of the associated text box, convert it to global time, and add that to the new values dictionary. Bind the original value in (in global time) to a hidden field in the same template, which will populate the old values dictionary with the correct old time. You'll want to do the same thing on insertion in OnItemInserting although you obviously don't need the old value (since there isn't one).
EDIT: Usually I do my updates on a DetailsView not a GridView, thus the ItemUpdating/Inserting instead of RowUpdating/Inserting. Sample code below -- this example uses a pair of dropdown lists that allows the user to specific a location (choose a building and a location in the building, but it actually only maps the location in the database). On the back end it assigns initial values to the dropdowns in OnPreRender (not shown) and extracts the LocationID database field value from the location dropdown on ItemUpdating/Inserting (updating shown). The DetailsView is wrapped in an UpdatePanel and the population of the Location dropdown is done when the building dropdown selection changes. Note that since I'm updating the item (causing an update statement anyway) I don't care if the LocationID field gets overwritten on the update with the same value so I don't bother to keep the old value on the page.
<asp:TemplateField HeaderText="Location:" SortExpression="LocationId">
<EditItemTemplate>
<asp:DropDownList runat="server" ID="buildingDropDownList"
DataSourceID="buildingDataSource"
DataTextField="name"
DataValueField="abbreviation"
OnSelectedIndexChanged=
"buildingDropDownList_SelectedIndexChanged"
AutoPostBack="true" />
<asp:DropDownList runat="server" ID="locationDropDownList"
DataSourceID="locationsDataSource"
DataTextField="Name"
DataValueField="ID">
</asp:DropDownList>
</EditItemTemplate>
<InsertItemTemplate>
<asp:DropDownList runat="server" ID="buildingDropDownList"
DataSourceID="buildingDataSource"
DataTextField="name"
DataValueField="abbreviation"
OnSelectedIndexChanged=
"buildingDropDownList_SelectedIndexChanged"
AutoPostBack="true"
AppendDataBoundItems="true">
<asp:ListItem Text="Select Building" Value="" />
</asp:DropDownList>
<asp:DropDownList runat="server" ID="locationDropDownList"
DataSourceID="locationsDataSource"
DataTextField="Name"
DataValueField="ID"
AppendDataBoundItems="true">
<asp:ListItem Text="Not installed" Value="" />
</asp:DropDownList>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="locationLabel" runat="server"\
Text='<%# Eval("LocationID") == null
? ""
: Eval("Location.Name") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
Codebehind:
void editPrinterDetailsView_ItemUpdating( object sender,
DetailsViewUpdateEventArgs e )
{
// Use a helper method to find the dropdown inside the details view
// and get the selected value.
string locationID = ControlHelper
.GetDropDownValue( editPrinterDetailsView,
"locationDropDownList" );
if (locationID == string.Empty)
{
locationID = null;
}
if (e.NewValues.Contains( "LocationID" ))
{
e.NewValues["LocationID"] = locationID;
}
else
{
e.NewValues.Add( "LocationID", locationID );
}
e.OldValues["LocationID"] = -1;
}

Resources