Hi,
I have a grid that reads in a bunch of number values from a database. These values are only ever either INT or Decimal(x,x)
When I try this after a UltraGrid AfterCellUpdate
if((Double)e.Cell.Value > 0)
But recieve an error that specific cast is not valid. The type returned by e.cell.value is Decimal and the Value = 3 in this test.
I tried this out and it works just fine for me.
What exactly is the exception? What does the call stack look like?
Line of Code in AfterCellUpdate event.
if
((double)e.Cell.Value < 0)
System.InvalidCastException was unhandled by user code Message="Specified cast is not valid." Source="UGTest" StackTrace: at Mitsic.frmcEquipment.ugEquip_AfterCellUpdate(Object sender, CellEventArgs e) in C:\Documents and Settings\rand\My Documents\Visual Studio 2008\Projects\UGTest\UGTest\frmcUgTestt.cs:line 7532 at Infragistics.Win.UltraWinGrid.UltraGrid.OnAfterCellUpdate(CellEventArgs e) at Infragistics.Win.UltraWinGrid.UltraGrid.FireEvent(GridEventIds id, EventArgs e) at Infragistics.Win.UltraWinGrid.UltraGridCell.SetValueInternal(Object value, Boolean suppressErrorMessagePrompt, Boolean fireInitializeRow, Boolean throwExceptionOnError, Boolean fireDataChanged) at Infragistics.Win.UltraWinGrid.UltraGridCell.SetValueInternal(Object value, Boolean suppressErrorMessagePrompt, Boolean fireInitializeRow, Boolean throwExceptionOnError) at Infragistics.Win.UltraWinGrid.UltraGridCell.SetValueInternal(Object value, Boolean suppressErrorMessagePrompt, Boolean fireInitializeRow) at Infragistics.Win.UltraWinGrid.UltraGridCell.CommitEditValue(Boolean& stayInEdit, Boolean fireDataError, Boolean forceDontThrowException, Boolean dontStoreInUndoHistory) InnerException:
Also , e.Cell.Value.GetType() == System.Decimal
The field in the database is Decimal(18,2)
Okay, I tried this again using the same code you are using and it looks like this is just a limitation of DotNet. It can't cast an object decimal directly into a double.
It looks like you will have to cast to a decimal first.This works:
decimal d = (Decimal)e.Cell.Value;if ((double)d > 0){ }
decimal d = (Decimal)e.Cell.Value;if ((double)d > 0){
}
Or another option would be to try to parse the value from a string:
double d; bool success = double.TryParse(e.Cell.Value.ToString(), out d); if (success && d > 0) {
Not according to this table:
http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx
and here
http://msdn.microsoft.com/en-us/library/364x0z75.aspx
I believe the difference here is that you are not attempting to convert a decimal to double. You are converting an object (that happens to be a decimal).
This code works fine:
decimal de = 5.5M; // Declare de as decimal double db = (double)de; Debug.WriteLine(db.ToString());
But this does not:
object de = 5.5M; // Declare de as object double db = (double)de; Debug.WriteLine(db.ToString());
Notice the difference in the first line where I declare de as object instead of decimal.
Anyway, none of this has anything to do with the WinGrid. So if you feel this is wrong, you will need to take it up with Microsoft. :)
There are a few things here that I have an issue with:
1) In your tutorial on Grid Performance, you have some examples of lines of code:
e.Row.Cells["Total"].Value = (double)e.Row.Cells["Quantity"].Value * (double)e.Row.Cells["Price"].Value;
Interestingly enough, if I try this it does not work, it has to be:
e.Row.Cells["Total"].Value = (decimal)e.Row.Cells["Quantity"].Value * (decimal)e.Row.Cells["Price"].Value;
2) Concerning your logic regarding not being able to cast an Object to Double that happens to be a decimal, why is not an issue to cast e.Cell.Value like this:
(Decimal)e.Cell.Value
but it is an issue to do this?
(Double)e.Cell.Value
melegant said:This whole converstaion has left me truly annoyed and ready to just rip out Infragistics and go with DevExpress. And when we make the move to Silverlight, I should go with who based on this conversation...
Well, I'm very sorry you feel that way. Perhaps it's sometimes hard to judge tone when reading text. But to me, it feels like I have been bending over backwards to try to help you out here, even though almost nothing about this discussion has anything to do with the WinGrid or any Infragistics products.
melegant said: The quick and simple answer would have been: When using a SQL Float the UltraGrid will translate as System.Double, whereas any other SQL Floating type # will come across as System.Decimal.
The quick and simple answer would have been:
When using a SQL Float the UltraGrid will translate as System.Double, whereas any other SQL Floating type # will come across as System.Decimal.
You started off in your original post asking why you are getting an error when you tried to cast a boxed decimal to a double in one operation. So you were obviously aware of the fact that some of your values were decimals. So I tried to explain why the error was occurring, since that is what you asked.
But just to be clear, the UltraGrid doesn't translate anything. It's not the grid that determines the data types of the fields. The grid simply creates columns based on the data source and it is the data source that determines what the fields are and their types. So whether you are getting doubles or decimals is up to the data source you are using and whatever you are using to retrieve the data.
This is what I mean by under the hood. Not that .Value is an object.
I have come to these forms because I expect you to be the expert in your product. Am I the lead developer? No. Do I make the decisions on what control sets to purchase? Yes. How do I base that decision? On the quality of support I receive.
This whole converstaion has left me truly annoyed and ready to just rip out Infragistics and go with DevExpress. And when we make the move to Silverlight, I should go with who based on this conversation...
melegant said:what is more important is that I understand more what is going under under the hood with the grid
Not sure what you mean by "under the hood" here. The Value property on the cell is an object. That's not under the hood, it's pretty much right out in the open. :)
The cell has to be able to deal with any data type, so the Value has to a object type. It's the same with a DataSet/DataTable, UltraDataSource, the Microsoft grid, or pretty much any other object that deals with fields of data. The cell can't very well expose a property of every possible data type. I suppose the grid could expose cells of a Generic type, but the grid was written long before generics were available on DotNet, so that was not an option at the time.
melegant said:Is there a way to specifiy that datatype of the column? I am using a datatable as the datasource for the grid.
There's a DataType property on the column. This gets set automatically based on the data structure of the data source the grid is bound to. But that doesn't change the fact that the Value property is (and has to be) an object. It's basically just for validation.
Ok, now we are getting somewhere.
So yes, I understand boxing but what is more important is that I understand more what is going under under the hood with the grid.
Basically if I have 2 columns from my database, one float and the other money (or decimal) then my cell values will be boxed up doubles and decimals respectivley. Since uboxing is an expensive process (as outlined in the article you sent over to me) I am going to just have to choose a datatype and go with it. It is a loose loose situation since I gain performance on the .NET side by using double but also gain performance on the SQL side by having a fixed point decimal vs a float.
All of this is null and void because I of having to perform 2 operations to get what I want. At some point then the grid is boxing up the cells to a datatype. Is there a way to specifiy that datatype of the column? I am using a datatable as the datasource for the grid. If I had that, then all issues are solved.
If you have an object which contains a decimal and you cast it to a decimal, you are simply unboxing it. That's fine and will work.
If you you have an object that contains a double and you try to cast it to a decimal, you are trying to unbox it and cast it in one operation. That's why it doesn't work.
I recommend that you take a look at Microsoft's documentation regarding casting and boxing.
Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4
http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx