我有一个VB.NET WinForms项目,我正在VS2013中构建。在绑定到DataSet的DataGridView中,我想突出显示用户已更改的每一行 - 如果用户将行的内容更改回其原始值(与数据库值相比),我想删除突出显示。
我已经谷歌搜索了一段时间,真的没有到达任何地方。
此时我所知道的是,在更改了单元格中的文本并单击该行之后,EmployeesDataSet.HasChanges(DataRowState.Modified)
在CellValueChanged事件中返回False。
我的假设是整个方法类似于KeyUp事件将当前行的单元格值与DataSet(或BindingSource或TableAdapter?)进行比较,如果有什么不同,请突出显示该行,否则将该行设置为默认值背景色。
但如果这是正确的方法,我不明白我将比较行的内容。它会是DataSet吗? TableAdapter? BindingSource?如果是其中之一,如何比较正确的行?
更新
更多研究取得了一些进展:
我找到了这个迭代代码:
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
For Each dt As DataTable In dsChanged.Tables
For Each row As DataRow In dt.Rows
For i As Integer = 0 To dt.Columns.Count - 1
Dim currentBackColor As System.Drawing.Color = dgvEmployees.AlternatingRowsDefaultCellStyle.BackColor
If Not row(i, DataRowVersion.Current).Equals(row(i, DataRowVersion.Original)) Then
dgvEmployees.Rows(dt.Rows.IndexOf(row)).DefaultCellStyle.BackColor = Color.LightPink
Else
' No changes so set it to its original color
dgvEmployees.Rows(dt.Rows.IndexOf(row)).DefaultCellStyle.BackColor = currentBackColor
End If
Next
Next
Next
我把它放在一个单独的Sub中,它在DataGridView.CellValueChanged事件中被调用。
这正确地检测到已更改单元格值的行,但是我为背景着色的代码并不完全正确。当我进行更改时,它会从上到下为每个连续的行着色 - 无论我编辑的DGV中的哪一行。
我认为dt.Rows.IndexOf(row)会正确获取DGV的正确索引,因为我正在迭代DGV的DataTable。
答案 0 :(得分:0)
好吧,如果你去寻找足够长的时间并花费足够的时间尝试不同的事情,你最终会找到答案......
这是我最终得到的工作代码:
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the correct row
CompareDgvToDataSource(e.RowIndex, e.ColumnIndex)
End Sub
Private Sub CompareDgvToDataSource(ByVal rowIndex As Integer, ByVal columnIndex As Integer)
If Not dgvEmployees Is Nothing And dgvEmployees.Rows.Count > 0 Then
' Condition required because this Method is also called when the DGV is being built and populated
Console.WriteLine("rowIndex: " & rowIndex.ToString() & ", columnIndex: " & columnIndex.ToString() & ", cell value: " & dgvEmployees.Rows(rowIndex).Cells(columnIndex).Value.ToString())
End If
' Force ending Edit mode so the last edited value is committed
EmployeesBindingSource.EndEdit()
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanged Is Nothing Then
For Each dt As DataTable In dsChanged.Tables
For Each row As DataRow In dt.Rows
For i As Integer = 0 To dt.Columns.Count - 1
If Not row(i, DataRowVersion.Current).Equals(row(i, DataRowVersion.Original)) Then
Console.WriteLine("Row index: " & dt.Rows.IndexOf(row))
dgvEmployees.Rows(rowIndex).DefaultCellStyle.BackColor = Color.LightPink
End If
Next
Next
Next
End If
End Sub
一些注意事项:
如果没有在BindingSource上调用EndEdit(),则不会检测到更改,因为CellValueChanged正在调用它,在更改BindingSource之前发生。
我尝试添加一个Else子句将BackColor设置为原始颜色(当检测到DGV行与DataSet的行相同或验证失败时),但我无法弄清楚如何解释正在设置DGV.AlternatingRowsDefaultCellStyle.BackColor属性。想法???
我认为这可以改进,因为我在Method中有行和列索引,只是直接转到DataSet的/ DataTable的相应行并进行比较,而不是遍历整个DataSet。关于那个的想法将不胜感激,但我会做一些更多的测试,看看我是否能得到它(我自己想到了这一点......)