保持DataGridView BindingSource不更新特定列的单元格值

问题描述 投票:1回答:1

我有一个使用DataGridViewDataTable绑定的BindingSource并且并非DataGridView中的所有列都与DataSource的属性绑定。更具体地说,我有一个用于多选的自定义DataGridViewColumn,它来自DataGridViewCheckBoxColumn类,并有一个主复选框,用于控制位于列标题中的其他选项。我的问题是,无论何时调用DataTable.AcceptChangesDataGridViewCheckBoxCell都会恢复其默认值(False),我将丢失之前的选择。有没有人知道一个很好的方法来防止或支持这种行为?

基本上,即使在调用DataTable.AcceptChanges之后,我仍希望保留该列中的单元格值,因为它们与底层数据源无关。

下面是一些示例代码,可以重现我正在经历的内容。检查选择列中的一些复选框并按Ctrl+S并注意每次都会丢失这些检查,即使它们没有绑定到特定的DataGridViewColumn。我意识到这可能是BindingSource的本质,但我想知道是否有办法绕过这种行为。另外,我想避免编写逻辑来保存在调用AcceptChanges之前选择的行,然后在AcceptChanges返回后重置它们。对我来说,如果我们一次在DataGridView选择了大量的行,这似乎太麻烦了。任何人都有一个更黑暗的想法?

Public Class Form1
  Sub New()
    InitializeComponent()
    Dim dgv As New DataGridView
    dgv.Columns.Add(New DataGridViewCheckBoxColumn With {.HeaderText = "Selection"})
    dgv.Columns.Add(New DataGridViewTextBoxColumn With {.HeaderText = "ChangeMe", .DataPropertyName = "ChangeMe"})
    Controls.Add(dgv) : dgv.Dock = DockStyle.Fill
    Dim dt = New DataTable : dt.Columns.Add("ChangeMe", GetType(String))
    For Each thing In {"Shoe", "Boat", "Rat"} : dt.Rows.Add(thing) : Next
    dgv.DataSource = New BindingSource(dt, Nothing)
    Me.KeyPreview = True
    AddHandler Me.KeyDown, Sub(sender As Object, e As KeyEventArgs)
                               If e.Control AndAlso e.KeyCode = Keys.S Then dt.AcceptChanges()
                           End Sub
  End Sub
End Class
vb.net winforms datagridview datatable bindingsource
1个回答
0
投票

这个问题是由于BindingSource响应BindingSource.ListChanged Event方法而引发ListChangedType.Reset类型的DataTable.AcceptChanges引起的。当DataGridView收到此事件时,它从BindingSource.重新加载这发生在ProcessListChanged Method(向下滚动到第658行)。

一个可能的解决方法是通过修改密钥处理程序方法来阻止BindingSource在执行DataTable.AcceptChanges期间引发事件,如下所示。

    AddHandler Me.KeyDown, Sub(sender As Object, e As KeyEventArgs)
                                            If e.Control AndAlso e.KeyCode = Keys.S Then
                                                Dim bs As BindingSource = DirectCast(dgv.DataSource, BindingSource)
                                                bs.RaiseListChangedEvents = False
                                                dt.AcceptChanges()
                                                bs.RaiseListChangedEvents = True
                                            End If
                                        End Sub
© www.soinside.com 2019 - 2024. All rights reserved.