我想得到一列datagridview的总和,并在文本框中显示。每次输入后,应动态更改总和。为此,我使用文本框的textChanged事件但是当输入时,它不显示任何结果。我想在文本框中动态获取结果。我想避免使用按钮进行求和。
以下是textbox textChanged事件的一段代码:
private void textBox9_TextChanged(object sender, EventArgs e)
{
double sum = 0;
for (int i = 0; i < dataGridView2.Rows.Count; ++i)
{
sum += Convert.ToDouble(dataGridView2.Rows[i].Cells[5].Value);
}
textBox9.Text = sum.ToString();
}
答案 0 :(得分:9)
你的代码是正确的,但我把它放在CellValueChanged事件中并检查以确保它是你正在寻找的同一个单元格。如果单元格的值发生更改,或者添加了新行并随后获取了值,则会触发此操作。
private void dataGridView2_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 5)
textBox9.Text = CellSum().ToString();
}
private double CellSum()
{
double sum = 0;
for (int i = 0; i < dataGridView2.Rows.Count; ++i)
{
double d = 0;
Double.TryParse(dataGridView2.Rows[i].Cells[5].Value.ToString(), out d);
sum += d;
}
return sum;
}
我把你的逻辑拆分成一个单独的方法,所以如果你想要得到其他东西的总和,你可以简单地调用那个方法。我想你可以阅读textbox.Text,但是......
我还使用了Double.TryParse,因为它提供了一些基本保护,因为给定单元格中的值实际上不是数字。我不知道数据来源是什么(用户输入/来自外部来源?)所以我想我会添加一些保护。
编辑格兰特提出了一个很好的观点,编辑了我的解决方案,包括修改单元格值。我使用了CellValueChanged事件而不是CellEndEdit,除了用户可以更改其值之外的其他事件。
答案 1 :(得分:3)
这是最简单的方法:
private void your_name()
{
Double your_variable = dataGridView1.Rows.Cast<DataGridViewRow>().Sum(x => Convert.ToDouble(x.Cells["Column4"].Value));
this.textBox1.Text = your_variable.ToString("N2");
}
答案 2 :(得分:2)
如果您需要考虑用户编辑网格行中现有值的可能性,您可以订阅CellEndEdit
事件。
在这里,我正在检查列索引,因此如果编辑了任何其他不相关的列,则不会重新计算总和。 (我也在验证输入并将值设置为0,如果有人输入字母。)
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 5)
{
decimal result;
if (!Decimal.TryParse(Convert.ToString(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value), out result))
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = 0;
textBox1.Text = dataGridView1.Rows.Cast<DataGridViewRow>()
.Sum(x => Convert.ToDecimal(x.Cells[5].Value))
.ToString();
}
}
其他人可能有更好的解决方案......这只是一种可能性。
答案 3 :(得分:1)
您必须处理事件CellValueChanged
。但是,您的方法有点不好,因为每次单元格的值发生更改时,您必须遍历所有行以更新总和。您应跟踪您的单元格更改以存储最后一个值,然后您可以轻松更新总和。需要首先使用循环计算总和。这只做了一次。
//This is used as CellTemplate for your interested column
public class TrackedValueDataGridViewCell : DataGridViewTextBoxCell {
public object OldValue { get; set; }
protected override bool SetValue(int rowIndex, object value) {
OldValue = Value;
return base.SetValue(rowIndex, value);
}
}
public partial class Form1 : Form {
public Form1(){
InitializeComponent();
//init your grid
dataGridView1.DataSource = yourDataSource;
dataGridView1.Columns["sumColumn"].CellTemplate = new TrackedValueDataGridViewCell();
sum = InitSum(dataGridView1,"sumColumn");
textBox9.Text = sum.ToString();
dataGridView1.CellValueChanged += (s,e) => {
if(dataGridView1.Columns[e.ColumnIndex].Name != "sumColumn") return;
var cell = ((TrackedValueDataGridViewCell) dataGridView1[e.ColumnIndex, e.RowIndex]);
sum -= ((double?) cell.OldValue).GetValueOrDefault();
sum += ((double?)cell.Value).GetValueOrDefault();
textBox9.Text = sum.ToString();
};
}
double sum;
public double InitSum(DataGridView grid, string colName) {
return grid.Rows.OfType<DataGridViewRow>()
.Sum(row => ((double?) row.Cells[colName].Value).GetValueOrDefault());
}
}
注意:我想您要总结的列名为sumColumn
,我们应该使用Name
来引用列,因为它更具可读性。上面的代码不计算添加新行和从网格中删除现有行的情况。实际上,无论何时以编程方式添加和删除,您都应该在添加和删除之前轻松更新sum
。要添加,我们可以处理RowsAdded
事件。以下所有事件处理程序注册都应放在某个Form.Load
事件处理程序中:
dataGridView1.RowsAdded += (s, e) => {
for (int i = e.RowIndex; i < e.RowIndex + e.RowCount; i++) {
sum += ((double?)dataGridView1["sumColumn", i].Value).GetValueOrDefault();
}
textBox9.Text = sum.ToString();
};
然而,对于删除行,这非常棘手。 RowsRemoved
不能很好地工作,我们不能再在RowsRemoved
事件处理程序中引用已删除的行,因此我们可能需要遍历所有行并更新总和:
dataGridView1.RowsRemoved += (s, e) => {
sum = InitSum(dataGridView1,"sumColumn");
textBox9.Text = sum.ToString();
};
用于删除代码和用户的行。另一个更好的选择是你必须处理UserDeletingRow
(但这只适用于按用户删除行,而不是代码)。要处理按代码删除行,我认为您可以在删除行的代码之前插入更新sum
的代码,这里是:
//for user removing rows
dataGridView1.UserDeletingRow += (s, e) => {
sum -= ((double?) e.Row.Cells["sumColumn"].Value).GetValueOrDefault();
textBox9.Text = sum.ToString();
};
//for code removing rows, use some method to remove rows like this:
public void RemoveRows(DataGridView grid, int startIndex, int count){
for(int i = startIndex; i <= startIndex + count; i++){
//update the sum first
sum -= ((double?)grid.Rows[i].Cells["sumColumn"].Value).GetValueOrDefault();
//then remove the row
grid.Rows.RemoveAt(startIndex);
}
textBox9.Text = sum.ToString();
}
请注意所有事件处理程序应在之后注册,您的网格已初始化,并且sum
初始化后会显示一些初始数据。
答案 4 :(得分:1)
private void dataGridView2_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 5)
{
summition();
}
}
void summition()
{
double sum = 0;
foreach (DataGridViewRow row in dataGridView2.Rows)
{
if(!row .IsNewRow )
sum += Convert.ToDouble(row.Cells [5].Value .ToString () );
}
textBox9.Text = sum.ToString();
}