VB.Net 从另一个窗体上的 DataGridView 更新现有的 Listview

VB.Net Update an existing Listview from a DataGridView on another Form

所以我有一个加载了 2 个 ListView 的表单。首先,lv1 随机填充票号。第二个,lv2 有一个启动 datagridview 表单的按钮,我在其中输入手动票号,并在输入票时在每个单元格中进行一系列错误检查。

如何让数据网格视图更新为列表视图?我尝试的一切,没有任何反应。我创建了一个表单,当 datagridview 和 listviews 都在同一个表单上并且它工作正常时,这是可能的。但是,我希望它可以跨表单工作。

  Private Sub cmdDone_Click(sender As Object, e As EventArgs) Handles cmdDone.Click
        dgv.AllowUserToAddRows = False
        FrmCycleCount.LvwYardTickets.Items.Clear()

        For i As Integer = 0 To Dgv.Rows.Count - 1
            Dim item As ListViewItem
              Dim arr(3) As String

            arr(0) = Dgv.Item(0, i).Value.ToString()
            arr(1) = gCycleYCnt
            arr(2) = "Yes"

            item = New ListViewItem(arr)
            FrmCycleCount.LvwYardTickets.Items.Add(item)
        Next
        dgv.AllowUserToAddRows = True
    End Sub

为了从表单传递数据,可以使用事件。无论表单是使用 Show() or ShowDiaglog() 打开的,这都有效。如果您正在使用 ShowDialog,那么还有另一种传回数据的方法,但由于您没有声明您打算使用 ShowDialog,因此我不会在这里讨论 - 我将使用 Show()

鉴于您有两种形式:

  • 表格 1
  • Form2

Form1 上有一个按钮 (btnAdd),单击时会打开 Form2。

首先,为数据创建一个class(名称:TicketInfo.vb)。

TicketInfo.vb

Public Class TicketInfo
    Private _found As String = String.Empty
    Private _pass As String = String.Empty
    Private _ticketNo As String = String.Empty

    Public Property Found As String
        Get
            Return _found
        End Get
        Set(value As String)
            _found = value
        End Set
    End Property

    Public Property Pass As String
        Get
            Return _pass
        End Get
        Set(value As String)
            _pass = value
        End Set
    End Property

    Public Property TicketNo As String
        Get
            Return _ticketNo
        End Get
        Set(value As String)
            _ticketNo = value
        End Set
    End Property

    Sub New()

    End Sub

    Sub New(ticketNo As String, pass As String)
        Me.TicketNo = ticketNo
        Me.Pass = pass
        Me.Found = Found
    End Sub

    Sub New(ticketNo As String, pass As String, found As String)
        Me.TicketNo = ticketNo
        Me.Pass = pass
        Me.Found = found
    End Sub

End Class

创建一个表单(名称:Form2.vb)并向其中添加一个 DataGridView。

添加两列:

  1. 工单#
  2. 通过

添加一个 ContextMenuStrip(从工具箱)到 Form2。然后在显示“在此处键入”的位置键入“删除”。双击“删除”一词创建事件处理程序。

为了使用事件将我们的数据传递给其他表单,我们将创建一个 class 和一个委托。

创建一个class(名称:DataGridViewValueUpdatedEventArgs.vb)

注意:我只定义了一个 属性,但如果需要,我们可以向 class 添加其他属性。我们还将把我们的代表放在这个文件中。但是,委托是在 class 之外定义的。请注意,委托的第二个参数是 class.

的名称

DataGridViewValueUpdatedEventArgs.vb

Public Delegate Sub DataGridViewValueUpdatedEventHandler(sender As Object, e As DataGridViewValueUpdatedEventArgs)

Public Class DataGridViewValueUpdatedEventArgs

    Public ReadOnly Property Tickets As List(Of TicketInfo)

    Sub New(tickets As List(Of TicketInfo))
        Me.Tickets = tickets
    End Sub

End Class

在 Form2 代码 (Form2.vb) 中,我们创建了一个可以由 Form2 中的代码引发的事件。请注意,DataGridViewValueUpdatedEventHandler 是我们委托的名称。

Public Event DataGridViewValueUpdated As DataGridViewValueUpdatedEventHandler

注意 class、委托和事件的命名策略。 class 名称和委托均以事件名称开头。

  • 事件:DataGridViewValueUpdated
  • 委托:“DataGridViewValueUpdated”+“EventHandler”=DataGridViewValueUpdatedEventHandler
  • Class: "DataGridViewValueUpdated" + "EventArgs" = DataGridViewValueUpdatedEventArgs

有关详细信息,请参阅 events

我们将使用 List(Of TicketInfo) 来保存我们的数据并将其传递回 Form1。

Private tickets As List(Of TicketInfo) = New List(Of TicketInfo)

单击 Done 按钮时,我们将从 DataGridView 获取数据并通过引发事件将其传回任何订阅者。

 Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
    'commit
    DataGridView1.EndEdit()

    'set value
    Dim lastRowIndex As Integer = DataGridView1.Rows.Count - 1

    If DataGridView1.Rows(DataGridView1.Rows.Count - 1).IsNewRow Then
        'set value
        lastRowIndex -= 1 'subtract 1
    End If

    'clear existing items
    tickets.Clear()

    For i As Integer = 0 To lastRowIndex
        'get values
        Dim ticketNo As String = DataGridView1.Rows(i).Cells(0).EditedFormattedValue.ToString()
        Dim pass As String = DataGridView1.Rows(i).Cells(1).EditedFormattedValue.ToString()

        'add
        tickets.Add(New TicketInfo(ticketNo, pass))
    Next

    'raise event (send data to subscribers)
    RaiseEvent DataGridViewValueUpdated(Me, New DataGridViewValueUpdatedEventArgs(tickets))

    'close
    Me.Close()
End Sub

在 Form1 中,我们将创建一个 Form2 的实例(名称:frm2)。

Private frm2 As Form2 = Nothing

Add 按钮 (btnAdd) 的 Click 事件处理程序中,我们将添加创建 Form2 新实例的代码(如果需要),并订阅 DataGridViewValueUpdated 事件,以及作为 FormClosed 事件。如果表单已最小化,我们将再次显示它。

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

    If frm2 Is Nothing Then
        'create new instance
        frm2 = New Form2()

        'subscribe to events (add event handlers)
        AddHandler frm2.DataGridViewValueUpdated, AddressOf Frm2_DataGridViewValueUpdated
        AddHandler frm2.FormClosed, AddressOf Frm2_FormClosed
        frm2.Show()
    Else
        frm2.WindowState = FormWindowState.Normal
        frm2.Activate()
    End If
End Sub

DataGridView2ValueUpdated 创建事件处理程序代码。

Frm2_DataGridViewValueUpdated

Private Sub Frm2_DataGridViewValueUpdated(sender As Object, e As DataGridViewValueUpdatedEventArgs)
    'ToDo: add desired code

    'set value
    Dim tickets As List(Of TicketInfo) = e.Tickets

    'clear existing items
    ListView2.Items.Clear()

    For Each ticket As TicketInfo In tickets
        Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
        Dim lvItem As ListViewItem = New ListViewItem(row)

        'add
        ListView2.Items.Add(lvItem)
    Next

    'set value
    TextBoxLv2TicketCount.Text = ListView2.Items.Count

End Sub

为 frm2 FormClosed 事件添加事件处理程序。当 frm2 关闭时,我们将删除我们的事件处理程序并将值设置为 Nothing。

Private Sub Frm2_FormClosed(sender As Object, e As FormClosedEventArgs)
    'unsubscribe from events (remove event handlers)
    RemoveHandler frm2.DataGridViewValueUpdated, AddressOf Frm2_DataGridViewValueUpdated
    RemoveHandler frm2.FormClosed, AddressOf Frm2_FormClosed

    'dispose
    frm2.Dispose()

    'set value
    frm2 = Nothing
End Sub

这是“Form1.vb”和“Form2.vb”的完整代码——“DataGridViewValueUpdatedEventArgs.vb”和“TicketInfo.vb”的完整代码可以在上面找到。

Form1.vb(完整代码)

Public Class Form1

    Private frm2 As Form2 = Nothing

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'set property
        ListView1.View = View.Details
        ListView2.View = View.Details

        'load test data
        LoadTestData()
    End Sub

    Private Sub LoadTestData()
        ListView1.Items.Clear()

        Dim lv1Tickets As New List(Of TicketInfo)

        lv1Tickets.Add(New TicketInfo("B034129", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B043999", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B044745", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B048767", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B050236", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B050960", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B052688", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B054892", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B882313", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B989873", "1", "No"))

        For Each ticket As TicketInfo In lv1Tickets
            Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
            Dim lvItem As ListViewItem = New ListViewItem(row)

            'add
            ListView1.Items.Add(lvItem)
        Next

        'set value
        TextBoxLv1TicketCount.Text = ListView1.Items.Count
    End Sub

    Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

        If frm2 Is Nothing Then
            'create new instance
            frm2 = New Form2()

            'subscribe to events (add event handlers)
            AddHandler frm2.DataGridViewValueUpdated, AddressOf Frm2_DataGridViewValueUpdated
            AddHandler frm2.FormClosed, AddressOf Frm2_FormClosed
            frm2.Show()
        Else
            frm2.WindowState = FormWindowState.Normal
            frm2.Activate()
        End If

    End Sub

    Private Sub Frm2_DataGridViewValueUpdated(sender As Object, e As DataGridViewValueUpdatedEventArgs)
        'ToDo: add desired code

        'set value
        Dim tickets As List(Of TicketInfo) = e.Tickets

        'clear existing items
        ListView2.Items.Clear()

        For Each ticket As TicketInfo In tickets
            Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
            Dim lvItem As ListViewItem = New ListViewItem(row)

            'add
            ListView2.Items.Add(lvItem)
        Next

        'set value
        TextBoxLv2TicketCount.Text = ListView2.Items.Count

    End Sub

    Private Sub Frm2_FormClosed(sender As Object, e As FormClosedEventArgs)
        'unsubscribe from events (remove event handlers)
        RemoveHandler frm2.DataGridViewValueUpdated, AddressOf Frm2_DataGridViewValueUpdated
        RemoveHandler frm2.FormClosed, AddressOf Frm2_FormClosed

        'dispose
        frm2.Dispose()

        'set value
        frm2 = Nothing
    End Sub

    Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
        Application.Exit()
    End Sub
End Class

Form2.vb(完整代码)

注意 下面的代码假定您在 Form2 上有一个 ContextMenuStrip(名称:ContextMenuStrip1)分配给 ContextMenuStrip 属性 DataGridView1.

Public Class Form2

    Public Event DataGridViewValueUpdated As DataGridViewValueUpdatedEventHandler
    Private tickets As List(Of TicketInfo) = New List(Of TicketInfo)

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click
        If MessageBox.Show("Are you sure you want to delete this row?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            'remove row
            DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
        End If
    End Sub

    Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
        'commit
        DataGridView1.EndEdit()

        'set value
        Dim lastRowIndex As Integer = DataGridView1.Rows.Count - 1

        If DataGridView1.Rows(DataGridView1.Rows.Count - 1).IsNewRow Then
            'set value
            lastRowIndex -= 1 'subtract 1
        End If

        'clear existing items
        tickets.Clear()

        For i As Integer = 0 To lastRowIndex
            'get values
            Dim ticketNo As String = DataGridView1.Rows(i).Cells(0).EditedFormattedValue.ToString()
            Dim pass As String = DataGridView1.Rows(i).Cells(1).EditedFormattedValue.ToString()

            'add
            tickets.Add(New TicketInfo(ticketNo, pass))
        Next

        'create new instance and set property
        'Dim args As DataGridViewValueUpdatedEventArgs = New DataGridViewValueUpdatedEventArgs(tickets)
        'raise event (send data to subscribers)
        'RaiseEvent DataGridViewValueUpdated(Me, args)

        'raise event (send data to subscribers)
        RaiseEvent DataGridViewValueUpdated(Me, New DataGridViewValueUpdatedEventArgs(tickets))

        'close
        Me.Close()
    End Sub

    Private Sub DeleteToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DeleteToolStripMenuItem.Click
        If MessageBox.Show("Are you sure you want to delete this row?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            'remove row
            DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
        End If
    End Sub
End Class


备用选项:

我将展示另一种使用事件和委托而不使用 class 的方法——下面的代码消除了对“DataGridViewValueUpdatedEventArgs.vb”的需要。我不会包含所有代码,而是突出显示 changes/differences.

Form2.vb(替代选项):

Public Class Form2
    Public Delegate Sub DataGridViewValueUpdatedEventHandler(sender As Object, e As List(Of TicketInfo))
    Public Event DataGridViewValueUpdated As DataGridViewValueUpdatedEventHandler
    Private tickets As List(Of TicketInfo) = New List(Of TicketInfo)
                       ...
    Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
                       ...
        RaiseEvent DataGridViewValueUpdated(Me, tickets)
                       ...
    End Sub
                       ...
End Class

Form1.vb(替代选项):

Public Class Form1
                   ...
    Private Sub Frm2_DataGridViewValueUpdated(sender As Object, e As List(Of TicketInfo))
    
        Dim tickets As List(Of TicketInfo) = e
                   ...
    End Sub
                   ...
End Class

这里有一个使用方法Show() - without using an event to pass the data. I also show how to use ShowDialog()

鉴于您有两种形式:

  • 表格 1
  • Form2

Form1 上有一个按钮 (btnAdd),单击时会打开 Form2。

首先,为数据创建一个class(名称:TicketInfo.vb)。

TicketInfo.vb

Public Class TicketInfo
    Private _found As String = String.Empty
    Private _pass As String = String.Empty
    Private _ticketNo As String = String.Empty

    Public Property Found As String
        Get
            Return _found
        End Get
        Set(value As String)
            _found = value
        End Set
    End Property

    Public Property Pass As String
        Get
            Return _pass
        End Get
        Set(value As String)
            _pass = value
        End Set
    End Property

    Public Property TicketNo As String
        Get
            Return _ticketNo
        End Get
        Set(value As String)
            _ticketNo = value
        End Set
    End Property

    Sub New()

    End Sub

    Sub New(ticketNo As String, pass As String)
        Me.TicketNo = ticketNo
        Me.Pass = pass
        Me.Found = Found
    End Sub

    Sub New(ticketNo As String, pass As String, found As String)
        Me.TicketNo = ticketNo
        Me.Pass = pass
        Me.Found = found
    End Sub
End Class

创建一个表单(名称:Form2.vb)并向其中添加一个 DataGridView。

添加两列:

  1. 工单#
  2. 通过

将 ContextMenuStrip(来自工具箱)添加到 Form2。然后在显示“在此处键入”的位置键入“删除”。双击“删除”一词创建事件处理程序。

我们将使用 List(Of TicketInfo) 来保存我们的数据并将其传递回 Form1-我们将使用 ReadOnly 属性。

Public ReadOnly Property Tickets As List(Of TicketInfo) = New List(Of TicketInfo)

注意:此时需要决定是使用Show还是ShowDialog。如果要允许用户在 Form2 打开时对 Form1 进行更改,请使用 Show()。如果您不希望用户在 Form2 打开时对 Form1 进行更改,请使用 ShowDialog().


选项 1 - 显示()

在 Form2 中,单击“完成”按钮时,我们将从 DataGridView 中获取数据,将其添加到列表中,然后关闭表单。

Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
    'commit
    DataGridView1.EndEdit()

    'set value
    Dim lastRowIndex As Integer = DataGridView1.Rows.Count - 1

    If DataGridView1.Rows(DataGridView1.Rows.Count - 1).IsNewRow Then
        'set value
        lastRowIndex -= 1 'subtract 1
    End If

    'clear existing items
    Tickets.Clear()

    For i As Integer = 0 To lastRowIndex
        'get values
        Dim ticketNo As String = DataGridView1.Rows(i).Cells(0).EditedFormattedValue.ToString()
        Dim pass As String = DataGridView1.Rows(i).Cells(1).EditedFormattedValue.ToString()

        'add
        Tickets.Add(New TicketInfo(ticketNo, pass))
    Next

    'close
    Me.Close()
End Sub

在 Form1 中,我们将创建一个 Form2 的实例(名称:frm2)。

Private frm2 As Form2 = Nothing

在添加按钮 (btnAdd) 的 Click 事件处理程序中,我们将添加代码来创建 Form2 的新实例(如有必要),并订阅 FormClosed 事件。如果表单已最小化,我们将再次显示它。

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

    If frm2 Is Nothing Then
        'create new instance
        frm2 = New Form2()

        'subscribe to events (add event handlers)
        AddHandler frm2.FormClosed, AddressOf Frm2_FormClosed

        'show form
        frm2.Show()
    Else
        frm2.WindowState = FormWindowState.Normal
        frm2.Activate()
    End If
End Sub

为 frm2 FormClosed 事件创建事件处理程序代码。当 frm2 关闭时,我们将删除事件处理程序并将 frm2 的值设置为 Nothing。

Private Sub Frm2_FormClosed(sender As Object, e As FormClosedEventArgs)

    'ToDo: add desired code

    'clear existing items
    ListView2.Items.Clear()

    For Each ticket As TicketInfo In frm2.Tickets
        Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
        Dim lvItem As ListViewItem = New ListViewItem(row)

        'add
        ListView2.Items.Add(lvItem)
    Next

    'set value
    TextBoxLv2TicketCount.Text = ListView2.Items.Count

    'dispose
    frm2.Dispose()

    'set value
    frm2 = Nothing
End Sub

这是“Form1.vb”和“Form2.vb”的完整代码——“TicketInfo.vb”的完整代码可以在上面找到。

Form1.vb(选项 1 - 完整代码)

Public Class Form1

    Private frm2 As Form2 = Nothing

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'set property
        ListView1.View = View.Details
        ListView2.View = View.Details

        'load test data
        LoadTestData()
    End Sub

    Private Sub LoadTestData()
        ListView1.Items.Clear()

        Dim lv1Tickets As New List(Of TicketInfo)

        lv1Tickets.Add(New TicketInfo("B034129", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B043999", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B044745", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B048767", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B050236", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B050960", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B052688", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B054892", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B882313", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B989873", "1", "No"))

        For Each ticket As TicketInfo In lv1Tickets
            Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
            Dim lvItem As ListViewItem = New ListViewItem(row)

            'add
            ListView1.Items.Add(lvItem)
        Next

        'set value
        TextBoxLv1TicketCount.Text = ListView1.Items.Count
    End Sub

    Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

        If frm2 Is Nothing Then
            'create new instance
            frm2 = New Form2()

            'subscribe to events (add event handlers)
            AddHandler frm2.FormClosed, AddressOf Frm2_FormClosed

            'show form
            frm2.Show()
        Else
            frm2.WindowState = FormWindowState.Normal
            frm2.Activate()
        End If

    End Sub

    Private Sub Frm2_FormClosed(sender As Object, e As FormClosedEventArgs)

        'ToDo: add desired code

        'clear existing items
        ListView2.Items.Clear()

        For Each ticket As TicketInfo In frm2.Tickets
            Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
            Dim lvItem As ListViewItem = New ListViewItem(row)

            'add
            ListView2.Items.Add(lvItem)
        Next

        'set value
        TextBoxLv2TicketCount.Text = ListView2.Items.Count

        'dispose
        frm2.Dispose()

        'set value
        frm2 = Nothing
    End Sub

    Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
        Application.Exit()
    End Sub
End Class

Form2.vb(选项 1 - 完整代码)

注意下面的代码假定您在 Form2 上有一个 ContextMenuStrip(名称:ContextMenuStrip1)分配给 DataGridView1 的 ContextMenuStrip 属性。

Public Class Form2
    Public ReadOnly Property Tickets As List(Of TicketInfo) = New List(Of TicketInfo)

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click
        If MessageBox.Show("Are you sure you want to delete this row?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            'remove row
            DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
        End If
    End Sub

    Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
        'commit
        DataGridView1.EndEdit()

        'set value
        Dim lastRowIndex As Integer = DataGridView1.Rows.Count - 1

        If DataGridView1.Rows(DataGridView1.Rows.Count - 1).IsNewRow Then
            'set value
            lastRowIndex -= 1 'subtract 1
        End If

        'clear existing items
        Tickets.Clear()

        For i As Integer = 0 To lastRowIndex
            'get values
            Dim ticketNo As String = DataGridView1.Rows(i).Cells(0).EditedFormattedValue.ToString()
            Dim pass As String = DataGridView1.Rows(i).Cells(1).EditedFormattedValue.ToString()

            'add
            Tickets.Add(New TicketInfo(ticketNo, pass))
        Next

        'close
        Me.Close()
    End Sub

    Private Sub DeleteToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DeleteToolStripMenuItem.Click
        If MessageBox.Show("Are you sure you want to delete this row?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            'remove row
            DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
        End If
    End Sub
End Class


选项 2 - ShowDialog()

在 Form2 中,单击“完成”按钮时,我们将从 DataGridView 中获取数据,将其添加到列表中,设置 DialogResult 的值,然后关闭表单。使用 ShowDialog() 时,btnAdd_Click 不会 return 直到 Form2 关闭。这意味着当 Form2 处于打开状态时,不能对 Form1 执行任何操作。使用下面的代码时,如果 Form2 最小化,单击 Form1 的任意位置,将再次显示 Form2。

Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
    'commit
    DataGridView1.EndEdit()

    'set value
    Dim lastRowIndex As Integer = DataGridView1.Rows.Count - 1

    If DataGridView1.Rows(DataGridView1.Rows.Count - 1).IsNewRow Then
        'set value
        lastRowIndex -= 1 'subtract 1
    End If

    'clear existing items
    Tickets.Clear()

    For i As Integer = 0 To lastRowIndex
        'get values
        Dim ticketNo As String = DataGridView1.Rows(i).Cells(0).EditedFormattedValue.ToString()
        Dim pass As String = DataGridView1.Rows(i).Cells(1).EditedFormattedValue.ToString()

        'add
        Tickets.Add(New TicketInfo(ticketNo, pass))
    Next

    'set value
    DialogResult = DialogResult.OK

    'close
    Me.Close()
End Sub

在 Form1 中,我们将创建一个 Form2 的实例(名称:frm2)。

Private frm2 As Form2 = Nothing

在添加按钮 (btnAdd) 的单击事件处理程序中,我们将添加代码来创建 Form2 的新实例,并订阅 Activated 事件。如果表单已最小化,我们将再次显示它。

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

    'create new instance
    frm2 = New Form2()

    'subscribe to events (add event handlers)
    AddHandler frm2.Activated, AddressOf Frm2_Activated

    If frm2.ShowDialog() = DialogResult.OK Then
        'clear existing items
        ListView2.Items.Clear()

        For Each ticket As TicketInfo In frm2.Tickets
            Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
            Dim lvItem As ListViewItem = New ListViewItem(row)

            'add
            ListView2.Items.Add(lvItem)
        Next

        'set value
        TextBoxLv2TicketCount.Text = ListView2.Items.Count
    End If

    'unsubscribe from events (remove event handlers)
    RemoveHandler frm2.Activated, AddressOf Frm2_Activated

    frm2.Dispose()
    frm2 = Nothing
End Sub

为 frm2 Activated 事件创建事件处理程序代码。当使用 ShowDialog() 并且 Form2 处于打开状态(即使最小化)时,单击 Form1 将激活 Form2。

Private Sub Frm2_Activated(sender As Object, e As EventArgs)
    'restore window
    frm2.WindowState = FormWindowState.Normal
End Sub

这是“Form1.vb”和“Form2.vb”的完整代码——“TicketInfo.vb”的完整代码可以在上面找到。

Form1.vb(选项 2 - 完整代码)

Public Class Form1

    Private frm2 As Form2 = Nothing
    Private frm2DialogResult As DialogResult = DialogResult.None

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'set property
        ListView1.View = View.Details
        ListView2.View = View.Details

        'load test data
        LoadTestData()
    End Sub

    Private Sub LoadTestData()
        ListView1.Items.Clear()

        Dim lv1Tickets As New List(Of TicketInfo)

        lv1Tickets.Add(New TicketInfo("B034129", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B043999", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B044745", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B048767", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B050236", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B050960", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B052688", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B054892", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B882313", "1", "No"))
        lv1Tickets.Add(New TicketInfo("B989873", "1", "No"))

        For Each ticket As TicketInfo In lv1Tickets
            Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
            Dim lvItem As ListViewItem = New ListViewItem(row)

            'add
            ListView1.Items.Add(lvItem)
        Next

        'set value
        TextBoxLv1TicketCount.Text = ListView1.Items.Count
    End Sub

    Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

        'create new instance
        frm2 = New Form2()

        'subscribe to events (add event handlers)
        AddHandler frm2.Activated, AddressOf Frm2_Activated

        If frm2.ShowDialog() = DialogResult.OK Then
            'clear existing items
            ListView2.Items.Clear()

            For Each ticket As TicketInfo In frm2.Tickets
                Dim row As String() = {ticket.TicketNo, ticket.Pass, ticket.Found}
                Dim lvItem As ListViewItem = New ListViewItem(row)

                'add
                ListView2.Items.Add(lvItem)
            Next

            'set value
            TextBoxLv2TicketCount.Text = ListView2.Items.Count
        End If

        'unsubscribe from events (remove event handlers)
        RemoveHandler frm2.Activated, AddressOf Frm2_Activated

        frm2.Dispose()
        frm2 = Nothing
    End Sub

    Private Sub Frm2_Activated(sender As Object, e As EventArgs)
        'restore window
        frm2.WindowState = FormWindowState.Normal
    End Sub

    Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
        Application.Exit()
    End Sub
End Class

Form2.vb(选项 2 - 完整代码)

Public Class Form2
    Public ReadOnly Property Tickets As List(Of TicketInfo) = New List(Of TicketInfo)

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click
        If MessageBox.Show("Are you sure you want to delete this row?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            'remove row
            DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
        End If
    End Sub

    Private Sub btnDone_Click(sender As Object, e As EventArgs) Handles btnDone.Click
        'commit
        DataGridView1.EndEdit()

        'set value
        Dim lastRowIndex As Integer = DataGridView1.Rows.Count - 1

        If DataGridView1.Rows(DataGridView1.Rows.Count - 1).IsNewRow Then
            'set value
            lastRowIndex -= 1 'subtract 1
        End If

        'clear existing items
        Tickets.Clear()

        For i As Integer = 0 To lastRowIndex
            'get values
            Dim ticketNo As String = DataGridView1.Rows(i).Cells(0).EditedFormattedValue.ToString()
            Dim pass As String = DataGridView1.Rows(i).Cells(1).EditedFormattedValue.ToString()

            'add
            Tickets.Add(New TicketInfo(ticketNo, pass))
        Next

        'set value
        DialogResult = DialogResult.OK

        'close
        Me.Close()
    End Sub

    Private Sub DeleteToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DeleteToolStripMenuItem.Click
        If MessageBox.Show("Are you sure you want to delete this row?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            'remove row
            DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
        End If
    End Sub
End Class