我有一个简单的数据表设置,连接到它的BindingSource和绑定到BindingSource的DataGridView。 DataTable填充了1个初始行。然后,我开始听BindingSource.Listchanged事件。
当我开始在DataGridView中编辑新行时,将触发具有ItemAdded类型的ListChanged事件。 BindingSource有2个项目,添加的项目是具有默认值的行。如果取消编辑,则会收到ListChanged ItemDeleted事件,到目前为止,这是合乎逻辑的。
但是,如果我输入新行,我将仅收到另一个ItemAdded通知,并且BindingSource再次包含2个项目。因此,我有两个 ItemAdded事件,但是只有一个项目被添加到BindingSource的基础列表中。
我现在要做的是跟踪BindingSource列表计数,如果没有更改,我将ItemAdded事件视为“ ItemReplace”事件。但是我想知道什么是处理这种情况的正确方法。
我附上了用于跟踪此事件的代码。
Imports System.ComponentModel
Public Class Form1
Dim bs As New BindingSource
Dim dt As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler bs.ListChanged, AddressOf OnListChanged
dt.Columns.Add("ID")
dt.Columns.Add("Name")
dt.Rows.Add("1", "Line 1")
bs.DataSource = dt
DataGridView1.DataSource = bs
End Sub
Private Sub OnListChanged(ByVal sender As Object, ByVal e As ListChangedEventArgs)
Select Case e.ListChangedType
Case ListChangedType.ItemAdded
TextBox1.Text += String.Format("ItemAdded Count:{0} NewIndex:{1}{2}", bs.List.Count, e.NewIndex, vbCrLf)
Case ListChangedType.ItemDeleted
TextBox1.Text += String.Format("ItemDeleted Count:{0} NewIndex:{1}{2}", bs.List.Count, e.NewIndex, vbCrLf)
Case ListChangedType.ItemChanged
TextBox1.Text += String.Format("ItemChanged Count:{0} NewIndex:{1}{2}", bs.List.Count, e.NewIndex, vbCrLf)
Case ListChangedType.ItemMoved
TextBox1.Text += String.Format("ItemMoved Count:{0} NewIndex:{1}{2}", bs.List.Count, e.NewIndex, vbCrLf)
Case ListChangedType.Reset
TextBox1.Text += String.Format("Reset Count:{0} NewIndex:{1}{2}", bs.List.Count, e.NewIndex, vbCrLf)
End Select
End Sub
End Class
更新微软在IBindingList上的docs中为两次射击提供了一些启示:
调用此方法时,应引发一个ListChanged事件,其中ItemAdded枚举带有适当的索引。添加的行处于以下状态:在DataGridView控件上单击Esc可以删除新行。在该行上用 second 时间引发具有ItemAdded枚举的ListChanged事件,表明该项目现在是普通行(不在新状态)。
因此,逻辑似乎是,在第一个ItemAdded通知之后,您将收到第二个ItemAdded通知(意味着保留该项目)或ItemDeleted通知(意味着丢弃先前添加的项目)。
但是问题是,当我使用ReadXML方法将数据加载到绑定的DataTable时,ListChanged事件每行仅引发一次。
一些测试表明,如果所添加项目的IsNew属性为true,则它是一个临时项目。这就是我可以从final分辨临时数据的方法。