how to get sum dynamically of datagridview column in textbox

后端 未结 5 1029
时光说笑
时光说笑 2021-01-14 00:00

I want to get the sum of a column of datagridview and show that in textbox. After each entry the sum should be changed dynamically. For that I am using textChanged event of

5条回答
  •  孤独总比滥情好
    2021-01-14 00:13

    You have to handle the event CellValueChanged. However your approach is a little bad because each time a cell's value changes, you have to loop through all the rows to update the sum. You should track your cell change to store the last value, then you can update the sum easily. The sum needs to be calculated initially using the loop. It's just done 1 time.

    //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()                       
                     .Sum(row => ((double?) row.Cells[colName].Value).GetValueOrDefault());
      }
    }
    

    NOTE: I suppose the column you want to sum up is named sumColumn, we should use Name to reference column because it's more readable. The code above doesn't count the cases when adding new rows and removing existing rows from grid. In fact, whenever adding and removing programmatically, you should update the sum easily right before adding and removing. For adding we can handle the RowsAdded event. All the following event handler registrations should be placed in some Form.Load event handler:

    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();
    };
    

    However for removing rows, it's very tricky. The RowsRemoved doesn't work well, we can't refer the removed rows anymore in the RowsRemoved event handler, so we may have to loop through all the rows and update the sum:

    dataGridView1.RowsRemoved += (s, e) => {
      sum = InitSum(dataGridView1,"sumColumn");
      textBox9.Text = sum.ToString();      
    };
    

    That's for removing rows by both code and user. Another option which is better is you have to handle the UserDeletingRow (but this works only for removing rows by user, not by code). To handle removing rows by code, I think you can always insert code updating the sum before any code removing the rows, here it is:

    //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();
    }
    

    Note that all the event handlers should be registered after your grid has been initialized with some initial data following by the sum initialization.

提交回复
热议问题