DataGridView updates datasource immediately after changing Checkbox value

I have a DataGridView System.Windows.Forms bound to a List<MyObject> .
The MyObject class contains the Boolean property associated with the DataGridViewCheckboxCell in the DataGridView.

 public class MyObject { public decimal DefaultValue {get; set; } public bool HasCustomValue {get;set; } public decimal CustomValue {get;set; } public decimal CurrentValue { get { return HasCustomValue ? CustomValue : DefaultValue; } } 

If I change the value of HasCustomValue , another (readonly) CurrentValue property also changes its value. This is done by implementing the INotifyPropertyChanged event (I left this part in the original example for simplicity)

If I change HasCustomValue outside the DataGridView, the column bound to CurrentValue will be updated immediately. In any case, if users enable / disable this check box, HasCustomValue will not be changed in the underlying data source if it does not leave the column by clicking with the mouse or by pressing the TAB key.

Is there a way to get the grid to update the data source right after changing the value of the checkbox?

If I bind a control property, I have the option to set the DataSourceUpdateMode on Windows.Forms.DataSourceUpdateMode.OnPropertyChanged , but I did not find anything like it in the DataGridView

+4
source share
5 answers

I assume you are using a bindingsource, and then in the Check Box Click event / Edited, do

  BindingSource.EndEdit() 
+2
source

I had a similar problem. And I did not use BindingSource , just a BindingList . After many frustrations and experiments (and after various solutions that didn't quite work),

I just did this:

  • override the DataGridView CellMouseUp event
  • in this case, call the DataGridView EndEdit() method.
+1
source

I did this trick:

  • Set the column with the CheckBox ReadOnly property to true.
  • Then, in the CellContentClick event handler, programmatically change the value to its opposite value.

     private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { int chkBoxColIdx = 0; //Index of the column with checkbox. if (e.ColumnIndex == chkBoxColIdx) { dataGridView1.Rows[e.RowIndex].Cells[chkBoxColIdx].Value = !(bool)dataGridView1.Rows[e.RowIndex].Cells[chkBoxColIdx].Value; } 
+1
source

Use handler for datagridview.CurrentCellDirtyStateChanged

 private void datagridview_CurrentCellDirtyStateChanged(Object sender, EventArgs e) { //_checkboxColumnIndex - index of your checkboxcolumn DataGridView dgv = (DataGridView)sender; if (_checkboxColumnIndex == dgv.CurrentCell.ColumnIndex && dgv.Columns[_checkboxColumnIndex].GetType() == typeof(DataGridViewCheckBoxColumn) && dgv.IsCurrentCellDirty == true) { //Remember that here dgv.CurrentCell.Value is previous/old value yet YourObject.HasCustomValue = !(bool)dgv.CurrentCell.Value } dgv.CommitEdit(DataGridViewDataErrorContexts.Commit) //this will fire .CellEndEdit event } 
+1
source

I can imagine that you do not want your bindingSource to know what it is attached to. In the end, not because you created a bindingSource: so that it can be attached to anything.

So you do not want to know how the value of your current element is; you only want to know that it has been changed.

To do this, you use the BindingSource.CurrentItemChanged event: any method is used to change data, you receive a notification.

The view associated with the BindingSource should inform the BindingSource that the change of value is complete; editing the property is over.

In your case, the view is a DataGridView. The DataGridView tells BindingSource that the current cell has completed the change using DataGridView.EndEdit ().

Usually, when you print a cell, editing ends when the cell loses focus, or when you press esc. This gives you the opportunity to correct input errors or cancel editing if you do not want changes.

However, in the case of a DataGridViewCheckBoxCell, most people expect to finish editing as soon as they click on a DataGridviewCheckBoxCell.

So you need to handle the DataGridView.CurrentCellDirtyStateChanged event

 // Whenever a DataGridViewCheckBoxCell becomes dirty editing is finished: private void OnCurrentCellDirtyChanged(object sender, EventArgs e) { if (this.dataGridView1.CurrentCell is DataGridViewCheckBoxCell; { this.dataGridView1.EndEdit(); } } 

This will throw the BindingSource.CurrentItemChanged event

+1
source

Source: https://habr.com/ru/post/1334085/


All Articles