简体   繁体   English

更改复选框值后,DataGridView立即更新数据源

[英]DataGridView update datasource directly after changed Checkbox value

I have a System.Windows.Forms DataGridView that is bound to a List<MyObject> . 我有一个绑定到List<MyObject>的System.Windows.Forms DataGridView。
The class MyObject contains a boolean property that is bound to DataGridViewCheckboxCell within the DataGridView. MyObject类包含一个布尔属性,该属性绑定到DataGridView中的DataGridViewCheckboxCell。

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) property CurrentValue changes it's value, too. 如果我更改HasCustomValue的值, HasCustomValue另一个(只读)属性CurrentValue也会更改其值。 That is done by implementing the INotifyPropertyChanged event (I left that part in the source example for simplicity) 这是通过实现INotifyPropertyChanged事件来完成的(为简单起见,我在源代码示例中保留了该部分)

If I changed HasCustomValue from outside the DataGridView, the column bound to CurrentValue gets updated immediately. 如果我从DataGridView外部更改了HasCustomValue ,则绑定到CurrentValue的列将立即更新。 Howevery, If the users enables/disables the checkbox, HasCustomValue is not changed in the underlying datasource unless he leaves the column by clicking with the mouse or pressing the TAB key. 但是,如果用户启用/禁用此复选框,则基础数据源中的HasCustomValue不会更改,除非他通过单击鼠标或按TAB键离开该列。

Is there a way to force the grid to update the datasource directly after changing a checkbox value? 有没有一种方法可以在更改复选框值后直接强制网格更新数据源?

If I bind a Control Property I have the ability to set the DataSourceUpdateMode to Windows.Forms.DataSourceUpdateMode.OnPropertyChanged but I haven't found anything like that in a DataGridView 如果绑定控件属性,则可以将DataSourceUpdateMode设置为Windows.Forms.DataSourceUpdateMode.OnPropertyChanged但在DataGridView中找不到类似的内容

I had a similar problem. 我有一个类似的问题。 And I wasn't using a BindingSource , just a BindingList . 而且我没有使用BindingSource ,而是使用BindingList After lots of frustration and experimentation (and following different solutions that didn't quite work), 经过大量的挫折和尝试(并遵循了不太奏效的不同解决方案),

I simply did this: 我只是这样做:

  • override the DataGridView 's CellMouseUp event 重写DataGridViewCellMouseUp事件
  • in the event, call the DataGridView 's EndEdit() method. 在这种情况下,调用DataGridViewEndEdit()方法。

我假设您使用的是bindingsource,然后在Check Box Click event / Edited上执行,

    BindingSource.EndEdit()

I did this trick: 我做了这个技巧:

  • Set the column's with CheckBox ReadOnly property to true. 将具有CheckBox ReadOnly属性的列设置为true。
  • Then in CellContentClick event handler programmatically change the value to its opposite value. 然后,在CellContentClick事件处理程序中,以编程方式将该值更改为其相反的值。

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

Use handler for datagridview.CurrentCellDirtyStateChanged 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
}

I can imagine that you don't want your bindingSource know to what it is bound to. 我可以想象您不希望您的bindingSource知道绑定到什么。 After all, isn't that why you created a bindingSource: to be able to let it be bound to bound to virtually anything. 毕竟,这不是您为什么创建bindingSource:使其能够绑定到几乎任何东西的原因。

So naturally, you don't want to know how the value of your current item is changed; 因此,您自然不希望知道当前项目的价值如何变化; you only want to know that it has been changed. 你只需要知道它已经被改变。

For this you use event BindingSource.CurrentItemChanged: whatever method is used to change the data, you get notified. 为此,您使用事件BindingSource.CurrentItemChanged:无论使用什么方法来更改数据,都会收到通知。

The view that is bound to the BindingSource has to tell the BindingSource that changing the value is finished; 绑定到BindingSource的视图必须告诉BindingSource更改值已完成; editing the property has ended. 属性的编辑已结束。

In your case the view is a DataGridView. 在您的情况下,该视图是DataGridView。 A DataGridView tells the BindingSource that the current cell has finished changing using DataGridView.EndEdit(). DataGridView使用DataGridView.EndEdit()告诉BindingSource当前单元格已完成更改。

Normally while you are typing the cell, the editing is ended when the cell loses focus, or when you press esc. 通常,在键入单元格时,当单元格失去焦点或按esc键时,编辑将结束。 This gives you the opportunity to correct typing errors or cancel editing in case you don't want the changes. 这使您有机会纠正输入错误或在不希望更改的情况下取消编辑。

However in case of a DataGridViewCheckBoxCell most people expect to finish editing as soon as the DataGridviewCheckBoxCell is clicked. 但是,对于DataGridViewCheckBoxCell,大多数人希望单击DataGridviewCheckBoxCell即可完成编辑。

Therefore you need to handle event DataGridView.CurrentCellDirtyStateChanged 因此,您需要处理事件DataGridView.CurrentCellDirtyStateChanged

// 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 lead to event BindingSource.CurrentItemChanged 这将导致事件BindingSource.CurrentItemChanged

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM