在很多很多情况下,数据实际上并不在DataGridView 中,而是在其他地方,例如DataTable 或某种集合(例如List<T>)。该控件只是向用户呈现数据视图。
有几种方法可以按照您的意愿进行操作。对于这两种情况,数据实际上驻留在DataTable 中。
表达式
可以为DataColumn 分配一个Expression。有关支持的表达式类型、关键字、运算符和函数,请参阅链接。以下将为某些行创建一个基于表达式的列到多个Quantity * Price:
dtSample = new DataTable();
dtSample.Columns.Add(new DataColumn("Item", typeof(string)));
dtSample.Columns.Add(new DataColumn("Quantity", typeof(int)));
dtSample.Columns.Add(new DataColumn("Price", typeof(decimal)));
dtSample.Columns.Add(new DataColumn("Sale", typeof(decimal)));
// assign expression using the col names
dtSample.Columns[3].Expression = "(Quantity * Price)";
添加一些随机数据以及空行后,DataTable 将为您维护这些列。这就像您可能希望的那样:如果用户(或代码)更改了Quantity 或Price 单元格的值,Sale 列的内容会自动更新。 (图片在第二种方法之后)。
Expressions 在行级别工作。没有像 TOTALS 行这样的全行/表格计数器部分 - 这是因为数据通常来自DataSource。添加计算行可能会意外地将新数据添加到该源(如数据库)。但是在代码中并不难做到:
事件驱动计算
与给出的 DGV CellFormatting 答案类似,您可以响应来自DataTable 的事件,例如RowChanged。在那里您可以执行任何操作并更新表格。
...create table and columns
...populate table
// hook up event
dtSample.RowChanged += RowChanged;
然后,在事件中,代码会计算每个单位的总体平均值以显示在最后一行。在某些情况下,您可以使用DataTable 的Compute() 方法。与Expression 不同,它不会自动更新,而as shown in this answer 更新起来可能很笨拙。
使用 DataTable 中的类型数据,执行计算以响应事件是相当容易的:
private void RowChanged(object sender, DataRowChangeEventArgs e)
{
// number of rows used
int Rows = dtSample.Rows.Count-1;
if (e.Row == dtSample.Rows[Rows]) return;
// display TotalSales / TotalUnits
// get the units
int TotUnits = dtSample
.AsEnumerable()
.Where(r => !r.IsNull("Quantity"))
.Take(Rows)
.Sum(n => n.Field<int>("Quantity"));
// sum Sales, divide and display in DGV
dtSample.Rows[Rows]["Price"] = dtSample
.AsEnumerable()
.Where(r => !r.IsNull("Sale"))
.Take(Rows)
.Sum(n => n.Field<decimal>("Sale")) / TotUnits;
}
“销售”列通过Expression 自动维护,这意味着您无法手动对该列执行任何操作。
底部的整体平均价格也是“自动”更新的,不同之处在于我们必须编写少量代码才能做到这一点。