You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET中DataGridView新增数据时通知弹窗不触发问题求助

问题描述

正在开发一款以MS Access为数据库的独立应用,当从应用中更新数据时,希望所有运行该应用的其他电脑上的DataGridView数据也能同步更新。我使用了LoadData()方法,但新增行时无法弹出通知弹窗。本人并非专业开发者,恳请各位提供帮助。

附上现有代码:

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        LoadData()
    End Sub

Private Sub dgvNotify_RowsAdded(sender As Object, e As DataGridViewRowsAddedEventArgs) Handles dgvNotify.RowsAdded
    Dim targetRow = Me.dgvNotify.Rows.Cast(Of DataGridViewRow)().OrderByDescending(Function(r) r.Cells("ID").Value).FirstOrDefault
    If targetRow IsNot Nothing Then
        targetRow.Selected = True
        New_Notification()
    End If

End Sub

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    Me.WindowState = FormWindowState.Minimized
    Me.Visible = False
    e.Cancel = True
End Sub

Private Sub New_Notification()
    NotifyIcon1.BalloonTipTitle = "New Important Notification"
    NotifyIcon1.BalloonTipText = "Open the notification application to check the notifications" & vbCrLf & "If you have any question reachout to ops leads:)"
    NotifyIcon1.ShowBalloonTip(3000)
End Sub
问题原因

你的代码里用Timer定时调用LoadData(),如果LoadData()是直接把新的DataTable赋值给DataGridView的DataSource,这种方式会一次性替换所有行,不会触发RowsAdded事件——这个事件只有在逐行添加行的时候才会被触发,批量替换数据源不会触发它,所以你的通知弹窗不会弹出。

解决方案

下面提供两种适合非专业开发者的实现方式,核心思路是对比新旧数据,找出新增行后触发通知:

方法一:对比新旧数据集,手动触发通知

这种方式适合数据量较大的场景,依然用批量替换数据源,但提前找出新增行:

  1. 先声明一个全局变量,保存上一次加载的数据集:
' 全局变量,保存上一次加载的数据
Private lastLoadedData As DataTable = New DataTable()
  1. 修改LoadData()方法(替换你原来的LoadData逻辑):
Private Sub LoadData()
    ' 第一步:从Access获取最新数据,这里替换成你实际取数据的代码
    ' 示例:假设你用OleDbConnection连接Access,填充DataTable
    Dim newData As DataTable = New DataTable()
    Using conn As New OleDb.OleDbConnection("你的Access连接字符串")
        conn.Open()
        Dim cmd As New OleDb.OleDbCommand("SELECT * FROM 你的表名", conn)
        Dim adapter As New OleDb.OleDbDataAdapter(cmd)
        adapter.Fill(newData)
    End Using

    ' 第一次加载时初始化数据
    If lastLoadedData.Rows.Count = 0 Then
        lastLoadedData = newData.Copy()
        dgvNotify.DataSource = newData
        Return
    End If

    ' 找出新增的行(假设ID是自增主键,用ID判断)
    Dim maxLastId As Integer = If(lastLoadedData.Rows.Count > 0, Convert.ToInt32(lastLoadedData.Compute("MAX(ID)", "")), 0)
    Dim hasNewRows = newData.AsEnumerable().Any(Function(row) Convert.ToInt32(row("ID")) > maxLastId)

    ' 更新DataGridView的数据源
    dgvNotify.DataSource = newData

    ' 如果有新增行,触发通知并选中最新行
    If hasNewRows Then
        ' 找到ID最大的行并选中
        Dim maxNewId = Convert.ToInt32(newData.Compute("MAX(ID)", ""))
        For Each row As DataGridViewRow In dgvNotify.Rows
            If Convert.ToInt32(row.Cells("ID").Value) = maxNewId Then
                row.Selected = True
                Exit For
            End If
        Next
        New_Notification()
    End If

    ' 更新上一次加载的数据
    lastLoadedData = newData.Copy()
End Sub

方法二:逐行添加新增数据(适合小数据量)

如果你的数据量不大,可以只添加新增的行,这样会触发RowsAdded事件,不用修改原有的事件逻辑:

  1. 同样先声明全局变量lastLoadedData,然后修改LoadData():
Private Sub LoadData()
    Dim newData As DataTable = New DataTable()
    ' 从Access获取最新数据,代码同方法一
    Using conn As New OleDb.OleDbConnection("你的Access连接字符串")
        conn.Open()
        Dim cmd As New OleDb.OleDbCommand("SELECT * FROM 你的表名", conn)
        Dim adapter As New OleDb.OleDbDataAdapter(cmd)
        adapter.Fill(newData)
    End Using

    ' 当前DataGridView绑定的数据
    Dim currentData As DataTable = DirectCast(dgvNotify.DataSource, DataTable)

    ' 第一次加载
    If currentData Is Nothing Then
        dgvNotify.DataSource = newData
        lastLoadedData = newData.Copy()
        Return
    End If

    ' 找出新增行
    Dim maxLastId As Integer = Convert.ToInt32(currentData.Compute("MAX(ID)", ""))
    Dim newRows = newData.AsEnumerable().Where(Function(row) Convert.ToInt32(row("ID")) > maxLastId)

    ' 逐行添加到当前数据集,这样会触发RowsAdded事件
    For Each row In newRows
        currentData.ImportRow(row)
    Next

    ' 更新上一次加载的数据
    lastLoadedData = newData.Copy()
End Sub
注意事项
  • 确保你的Access表中ID字段是自增主键,这样才能通过ID判断哪些是新增行
  • Timer的间隔不要设置太频繁(比如不要小于5秒),避免频繁访问数据库导致程序卡顿或数据库压力过大
  • 可以在取数据的代码里加Try-Catch捕获异常,防止数据库连接出错导致Timer停止工作

内容的提问来源于stack exchange,提问作者Eragon006

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:55:19