DataGridView 在更改 Checkbox 值后直接更新数据源

发布于 2024-10-10 00:15:25 字数 1034 浏览 3 评论 0原文

我有一个绑定到 List 的 System.Windows.Forms 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;
        }
}

如果我更改 HasCustomValue 的值,另一个(只读)属性 CurrentValue 也会更改它的值。 这是通过实现 INotifyPropertyChanged 事件来完成的(为了简单起见,我将该部分留在了源示例中)

如果我从 DataGridView 外部更改了 HasCustomValue,绑定到 CurrentValue 的列就会更新立即地。 但是,如果用户启用/禁用该复选框,则底层数据源中的 HasCustomValue 不会更改,除非用户通过单击鼠标或按 TAB 键离开该列。

有没有办法强制网格在更改复选框值后直接更新数据源?

如果我绑定一个控件属性,我可以将 DataSourceUpdateMode 设置为 Windows.Forms.DataSourceUpdateMode.OnPropertyChanged 但我没有在 DataGridView 中找到类似的内容

I have a System.Windows.Forms DataGridView that is bound to a List<MyObject>.
The class MyObject contains a boolean property that is bound to DataGridViewCheckboxCell within 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) property CurrentValue changes it's value, too.
That is done by implementing the INotifyPropertyChanged event (I left that part in the source example for simplicity)

If I changed HasCustomValue from outside the DataGridView, the column bound to CurrentValue gets updated immediately.
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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

眼前雾蒙蒙 2024-10-17 00:15:25

我假设您正在使用绑定源,然后在复选框单击事件/编辑上执行,

    BindingSource.EndEdit()

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

    BindingSource.EndEdit()
东风软 2024-10-17 00:15:25

我有类似的问题。我没有使用 BindingSource,只是使用 BindingList。经过大量的挫折和实验(并遵循了不太有效的不同解决方案),

我简单地这样做了:

  • 覆盖 DataGridViewCellMouseUp 事件
  • 在事件中 ,调用DataGridViewEndEdit() 方法。

I had a similar problem. And I wasn't using a BindingSource, just a 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
  • in the event, call the DataGridView's EndEdit() method.
南汐寒笙箫 2024-10-17 00:15:25

我做了这个技巧:

  • 将列的 CheckBox ReadOnly 属性设置为 true。
  • 然后在 CellContentClick 事件处理程序中以编程方式将该值更改为相反的值。

    private void dataGridView1_CellContentClick(对象发送者,DataGridViewCellEventArgs e)
    {
        int chkBoxColIdx = 0; //带有复选框的列的索引。
        if (e.ColumnIndex == chkBoxColIdx)
        {
            dataGridView1.Rows[e.RowIndex].Cells[chkBoxColIdx].Value = !(bool)dataGridView1.Rows[e.RowIndex].Cells[chkBoxColIdx].Value;
        }
    

I did this trick:

  • Set the column's with CheckBox ReadOnly property to true.
  • Then in 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;
        }
    
这个俗人 2024-10-17 00:15:25

使用 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
}

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
}
似狗非友 2024-10-17 00:15:25

我可以想象您不希望您的 BindingSource 知道它所绑定的内容。毕竟,这不正是您创建 BindingSource 的原因:能够让它绑定到几乎任何东西。

因此,您自然不想知道当前商品的价值如何发生变化;您只想知道它已被更改。

为此,您可以使用事件 BindingSource.CurrentItemChanged:无论使用什么方法来更改数据,您都会收到通知。

绑定到 BindingSource 的视图必须告诉 BindingSource 值更改已完成;属性编辑已结束。

在您的情况下,视图是 DataGridView。 DataGridView 使用 DataGridView.EndEdit() 告诉 BindingSource 当前单元格已完成更改。

通常,当您键入单元格时,当单元格失去焦点或按 esc 时,编辑就会结束。这使您有机会更正输入错误或在您不需要更改时取消编辑。

但是,对于 DataGridViewCheckBoxCell,大多数人希望在单击 DataGridviewCheckBoxCell 后立即完成编辑。

因此,您需要处理事件 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();
    }
}

这将导致事件 BindingSource.CurrentItemChanged

I can imagine that you don't want your bindingSource know to what it is bound to. After all, isn't that why you created a bindingSource: to be able to let it be bound to bound to virtually anything.

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.

The view that is bound to the BindingSource has to tell the BindingSource that changing the value is finished; editing the property has ended.

In your case the view is a DataGridView. A DataGridView tells the BindingSource that the current cell has finished changing using DataGridView.EndEdit().

Normally while you are typing the cell, the editing is ended when the cell loses focus, or when you press 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.

Therefore you need to handle event 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文