1

我有一个可以在整个应用程序中访问的共享/静态DataTable 。表单上,​​我有一个绑定到DataTable的DataViewDataGridView我的问题是DataGridView未捕获DataTable的跨线程更新,尽管基础数据源(DataView)已更新。

我已经尝试过DataGridView的 update、invalidate、refresh 和 resetbindings 方法,但仍然没有添加、删除或更新行。

'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'
4

2 回答 2

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
于 2013-02-09T02:05:45.803 回答
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与.DataView

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    Me.view.Refresh()
End Sub
于 2014-02-03T18:37:51.480 回答