26

I have a Winforms app written in C#.

In one of my DataGridViews I have set all columns except one called 'Reference' to ReadOnly = true;

I want the application to know when a User has changed anything in the 'Reference' column, but all the events I have tried so far fire a lot more than when a user has made changes. For example CurrentCellChanged fires when the DataGridView is initially rendered and everytime the user simply clicks or tabs along the rows etc.

I'm only interested in catching user changes to data in the 'Reference' column which is the ONLY column where ReadOnly = false;

Which is the best event to use for this?

PJW
  • 5,197
  • 19
  • 60
  • 74

2 Answers2

34

CellValueChanged is what you need:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e){
  if(dataGridView1.Columns[e.ColumnIndex].Name == "Reference"){
    //your code goes here
  }
}

I think the event CellEndEdit is also suitable for your want:

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e){
  if(dataGridView1.Columns[e.ColumnIndex].Name == "Reference"){
    //your code goes here
  }
}
King King
  • 61,710
  • 16
  • 105
  • 130
  • 11
    I vote for your second solution: `private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e){ if(dataGridView1.Columns[e.ColumnIndex].Name == "Reference"){ //your code goes here } }` because the first fires each time a value in the cell changes even if the action hasn't be trigged by user. I.E. if I've a method that adds rows in background CellValueChanged will fire. – Luke Sep 11 '15 at 10:20
  • 2
    The second solution (CellEndEdit event) also fires when the value hasn't changed though - for example, even when the user presses "esc" to end editing without changing the value. – JPProgrammer Jan 28 '16 at 08:30
  • 1
    @JPProgrammer - I found a way to avoid that, see [below](https://stackoverflow.com/a/58062911/1016343) my addition to King King's good answer. – Matt Sep 23 '19 at 12:56
2

In my case CellValueChanged event was also triggering while the DGV was initializing, so I wanted to use CellEndEdit, as King King mentioned in his answer.

To make King King's second answer more bullet-proof (see JPProgrammer's comment), i.e. only react, if a value was entered in the cell, you can do the following:

   private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
   {
        int? rowIdx = e?.RowIndex;
        int? colIdx = e?.ColumnIndex;
        if (rowIdx.HasValue && colIdx.HasValue)
        {
            var dgv = (DataGridView)sender;
            var cell = dgv?.Rows?[rowIdx.Value]?.Cells?[colIdx.Value]?.Value;
            if (!string.IsNullOrEmpty(cell?.ToString()))
            {
                // your code goes here
            };
        };
   }

Notice the null handling by using ?. and ?[ operators. I have written it so that it can be used in a more general way, but of course you can add the check for the "Reference" column, just replace the inner if statement above by the following:

       if (dgv.Columns[colIdx.Value].Name == "Reference")
       {
          if (!string.IsNullOrEmpty(cell?.ToString()))
          {
               // your code goes here
          };
       };
Matt
  • 25,467
  • 18
  • 120
  • 187