C# 更正事件以计算DataGridView中的单元格值

C# 更正事件以计算DataGridView中的单元格值,c#,winforms,datagridview,C#,Winforms,Datagridview,在DataGridView中,我在CellEndEdit事件中使用此代码自动计算乘以数量的金额: private void myGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e) { DataGridView oDGV = (DataGridView)sender; DataGridViewCell oCell = oDGV.Rows[e.RowIndex].Cells[e.ColumnIndex];

在DataGridView中,我在
CellEndEdit
事件中使用此代码自动计算乘以数量的金额:

private void myGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    DataGridView oDGV = (DataGridView)sender; 
    DataGridViewCell oCell = oDGV.Rows[e.RowIndex].Cells[e.ColumnIndex];

    // Only the quantity can be changed
    if (oCell.Value != DBNull.Value && oCell.OwningColumn.Name == "num")
    {
        oDGV.EndEdit(); 
        int nNum = Convert.ToInt16(oCell.Value);
        decimal nPrice = Convert.ToDecimal(oDGV.Rows[e.RowIndex].Cells["price"].Value.ToString());
        decimal nTot = nPrice * nNum;
        oDGV.Rows[e.RowIndex].Cells["tot"].Value = nTot;
    }
}
显然这是一个简单的操作,但我经常会遇到这样的情况,即没有执行计算,我必须返回单元格,再次键入值并按enter键(即使屏幕上的所有内容都正确)。

我不明白问题出在哪里,也许我必须使用另一个事件?

您有3列需要交互:

  • 价格
    列:它应该指定一个
    单价
  • num
    列:应该是项目的数量,
    数量
  • tot
    列:由
    [单价]*[数量]
由于第三列(
总计
)的值是将价格(
单价
)乘以项目的数量(
数量
)得到的,因此此计算可以转移到a:此操作是固定的(它总是指相同的列,它们总是具有相同的值类型)

当然,在代码中,您可以使用已分配给列的名称:

[Your DataTable].Columns["tot"].Expression = "[price] * [num]";
► 请注意,由于您要表示价格(货币),因此可能需要使用十进制类型来表示该值,而不是整数类型。这同样适用于
Total

可以在加载DataTable之后,或者在将其分配给
DataGridView.DataSource
属性之后立即分配表达式。
分配属性时,将引发事件:

private void myGrid_DataSourceChanged(object sender, EventArgs e)
{
    if (myGrid.DataSource is DataTable dt && dt.Columns.IndexOf("tot") >= 0) {
        dt.Columns["tot"].Expression = "[num] * [price]";
    }
}
► 单元格不需要包含值,
[单价]
[数量]
都可以
null
,不会引发异常。当然,您可以使用DataGridView
NewRow
向DataTable添加新行

若要在
单价
数量
值更改后立即更改
总计
列的值,请订阅
CellEndEdit
CellValueChanged
事件并验证编辑。在这种情况下,无需按Enter键或change Row键即可看到新的计算值,只需将光标移动到另一个相邻单元格(Excel样式)


如果DataGridView的数据源是DataTable,则可以向
tot
列添加表达式。它将自动计算总值,乘以其他两列的值。不需要编辑任何内容。如果是类对象,则在内部添加相同的逻辑(计算其他两个属性值的属性),该类对象应实现
INotifyPropertyChanged
。使用BindingSource可以更好地处理类对象的集合。
private void myGrid_DataSourceChanged(object sender, EventArgs e)
{
    if (myGrid.DataSource is DataTable dt && dt.Columns.IndexOf("tot") >= 0) {
        dt.Columns["tot"].Expression = "[num] * [price]";
    }
}
private void myGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    Validate();
}