CurrentCellDeactivated is not a good place to do this kind of thing. First it is called too often, and the is without an active cell at this point. The first exception, you are seeing is due to an initial DeactivateCell as the clicked cell is getting focus. After that, there are other exceptions being thrown by trying to parse as a double a value of DBNull. I think all these tings are contributing the weird new row behavior because the exceptions are being thrown as you click into a empty row.
Anyway, I think you can tweak your code an dmove it to CurrentCellConfirmChanges, and get things to work without these problems. Here is the handler I tried.
private void gridDataBoundGrid1_CurrentCellAcceptedChanges(object sender, CancelEventArgs e)
{
try
{
GridCurrentCell cc = this.gridDataBoundGrid1.CurrentCell;
int row = cc.RowIndex;
int priceColIndex = gridDataBoundGrid1.NameToColIndex("Price");
int qtyColIndex = gridDataBoundGrid1.NameToColIndex("Qty");
int totalColIndex = gridDataBoundGrid1.NameToColIndex("Total");
if(cc.ColIndex == priceColIndex || cc.ColIndex == qtyColIndex)
{
decimal price = ParseDecimal(gridDataBoundGrid1[row, priceColIndex].CellValue, 0.00M);
decimal qty = ParseDecimal(gridDataBoundGrid1[row, qtyColIndex].CellValue, 0.00M);
Console.WriteLine("Row="+row+", price="+price+", qty="+qty);
Console.WriteLine("RowCount=" + gridDataBoundGrid1.Model.RowCount);
gridDataBoundGrid1[row, totalColIndex].CellValue = price * qty;
this.gridDataBoundGrid1.RefreshRange(GridRangeInfo.Cell(row, totalColIndex));
}
}
catch(Exception ex)
{
Console.WriteLine("Error: " + ex);
}
}
To handle the DBNull problem I added an etra condition to your parse code.
if(o != null && o != DBNull.Value)