我有一个共享/静态 DataTable ,可以在整个应用程序中访问。 在表单上,我有 DataGridView 绑定到 DataTable 的 DataView 。 我的问题是 DataTrid 的跨线程更新没有被 DataGridView 捕获,尽管基础数据源(DataView)已更新。
我已经尝试了 DataGridView 的更新,无效,刷新和重置绑定方法,但仍然没有添加,删除或更新行。
'The following example requires:
'-----------------------------------------------------------------------------
'Friend WithEvents DataGridView1 As System.Windows.Forms.DataGridView
'Friend WithEvents Button1 As System.Windows.Forms.Button
'Friend WithEvents Button2 As System.Windows.Forms.Button
'Friend WithEvents BackgroundWorker1 As System.ComponentModel.BackgroundWorker
'-----------------------------------------------------------------------------
Public Class Form1
Shared Sub New()
Repository = New DataTable()
End Sub
Public Sub New()
Me.InitializeComponent()
Me.view = New DataView(Repository)
Me.DataGridView1.DataSource = Me.view
End Sub
'Updates the DataGridView correctly.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Using table As DataTable = GetUpdatedDataTable()
SyncLock Repository
Repository.Merge(table)
End SyncLock
End Using
End Sub
'Do NOT update the DataGridView correctly (cross-thread)
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
If (Not Me.BackgroundWorker1.IsBusy) Then
Me.BackgroundWorker1.RunWorkerAsync()
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Using table As DataTable = GetUpdatedDataTable()
SyncLock Repository
Repository.Merge(table)
End SyncLock
End Using
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Me.DataGridView1.Update()
Me.DataGridView1.Refresh()
Me.DataGridView1.Invalidate(False)
Me.DataGridView1.Invalidate(True)
Me.DataGridView1.ResetBindings()
MsgBox(Me.view.Count)
End Sub
Private Shared Function GetUpdatedDataTable() As DataTable
Dim table As New DataTable("TEST")
table.Columns.AddRange(New DataColumn() {New DataColumn("ID", GetType(Integer)), New DataColumn("TEXT", GetType(String))})
table.Rows.Add(Repository.Rows.Count, String.Format("Row #{0}", Repository.Rows.Count))
table.AcceptChanges()
Return table
End Function
Public Shared Repository As DataTable
Private ReadOnly view As DataView
End Class'
答案 0 :(得分:0)
您应该尝试以下方式而不是刷新:
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Me.DataGridView1.Update()
Me.DataGridView1.DataSource = Nothing
Me.DataGridView1.DataSource = Repository
Me.DataGridView1.Invalidate(False)
Me.DataGridView1.Invalidate(True)
Me.DataGridView1.ResetBindings()
MsgBox(Me.view.Count)
End Sub
答案 1 :(得分:0)
由于这个问题很快就要庆祝它的第一个“生日”,所以最好还是给它一个最终答案。 DataGridView
未更新的原因是因为DataView.ListChanged
事件(DGV挂钩)在工作线程而不是UI线程上引发。
选项1
在UI线程上进行合并。
Me.Invoke(Sub() Repository.Merge(table))
当然,这将冻结应用程序,直到合并完成。
选项2
对DataView
进行子类化,并使其能够在需要时引发ListChanged
事件。
Public Class DataViewEx
Inherits DataView
Public Sub New()
End Sub
Public Sub New(table As DataTable)
MyBase.New(table)
End Sub
Public Sub New(table As DataTable, rowFilter As String, sort As String, rowState As DataViewRowState)
MyBase.New(table, rowFilter, sort, rowState)
End Sub
Public Sub Refresh()
Me.OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
End Class
现在,一旦工作人员完成了任务,所有人必须做的就是调用Refresh
方法,而DataGridView
“与{同步” {1}}。
DataView