简体   繁体   中英

DataGridView - Calculate and update a cell value based on other cells

I have DataGridView whos datasouce is a bindingList and I need to do some calculations based on user data entry.

I want to allow to be able to allow a user to enter a value in the Sell Value Column [Column 7]) which is then used with a value in another cell (Cost Value [col 8]) to calculate a value for another cell in the row, a Margin Value [Col 9].

i.e. 
Col 9 = col 7 - Col 8  (Margin = Sell Value -cost Value)

I've got this code in the CellValidating event of the DGV. The Case parameter is the Column index. Its a bit wordy as I've been using debug statements to check how its going.

                Case 7
                Debug.Print("Checking Sell Value")
                If Not IsNumeric(dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(e.ColumnIndex).EditedFormattedValue) Then
                    Debug.Print("Not a valid sell value")
                    dgvPurchaseOrderItems.Rows(e.RowIndex).ErrorText = "Need a valid sell value."
                    e.Cancel = True
                End If
                'update Margin Value
                Debug.Print("Sell Value OK - so updating Margin value")
                Debug.Print("Sell (edited Value): " & dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(7).EditedFormattedValue)
                Debug.Print("Sell (Value): " & dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(7).Value)

                SellValue = Convert.ToDecimal(dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(7).EditedFormattedValue)
                Debug.Print("Sell Value (decimal): " & SellValue)
                costvalue = Convert.ToDecimal(dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(8).Value)
                Debug.Print("Cost Value (decimal): " & costvalue)
                MarginValue = SellValue - costvalue
                Debug.Print("Margin Value:" & MarginValue)
                dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(9).Value = MarginValue

            Case 8
                Debug.Print("Checking Cost Value ")
                If Not IsNumeric(dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(e.ColumnIndex).EditedFormattedValue) Then
                    Debug.Print("Not a valid cost value")
                    dgvPurchaseOrderItems.Rows(e.RowIndex).ErrorText = "Need a valid cost value."
                    e.Cancel = True
                End If
                'update Margin Value
                Debug.Print("Cost Value OK - so updating Margin value")
                Debug.Print("Sell (edited Value): " & dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(7).EditedFormattedValue)
                Debug.Print("Sell (Value): " & dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(7).Value)
                Debug.Print("Cost (edited Value): " & dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(8).EditedFormattedValue)
                Debug.Print("Cost (Value): " & dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(8).Value)

                SellValue = Convert.ToDecimal(dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(7).Value)
                Debug.Print("Sell Value (decimal): " & SellValue)
                costvalue = Convert.ToDecimal(dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(8).EditedFormattedValue)
                Debug.Print("Cost Value (decimal): " & costvalue)
                MarginValue = SellValue - costvalue
                Debug.Print("Margin Value:" & MarginValue)
                dgvPurchaseOrderItems.Rows(e.RowIndex).Cells(9).Value = MarginValue

However, whilst it seems to update Cell 9, the contents of Col 7 is set to 0 again.

Am I going about this in the right way? SHould I be using the CellValidating event or something different? I cant understand why the of the cell just entered is being reset to the original values when I'm not cancelling the edit?

Ah, I did the calculation in properties of the underlying bindinglist. That seems to work.

Question remains - should I be changing the values of cells in the cellValidating event, the bindinglists properties or somewhere else?

THanks

The answer is not to update a column directly by using a calculation in the CellValidating Event.

Rather, change the value in the backend datasource and rely on the 2-way binding between the datasource and the DGV to show the change back to the user.

SO I have have this in the sell_value property now and similar in the cost_value Property.

When a user changes the sell or cost value in the DGV, a call is made back to the binding list setting these properties, which then runs the calulation to find the Margin cost, which is then automatically updated in the read-only column displaying this property.

Public Property sell_value() As Decimal
    Get
        Return _sell_value
    End Get
    Set(ByVal value As Decimal)
        _sell_value = value
        Debug.Print("Setting margin value in Sell_value Property")
        margin_value = _sell_value - _cost_value
        Debug.Print("Setting margin % in sell_value Property")
        If sell_value <> 0 Then
            margin_percent = _margin_value / sell_value
        Else
            margin_percent = 0
        End If
    End Set
End Property

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM