If you want to add the spaces for formatting purposes, I think that you can consider the CellFormatting event. See how ShortFormDateFormat was used to display a custom value: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.cellformatting.
datagridview access row when added without the need to loop through rows
I have a datagridview to represent journal voucher debit/credit binded to bindingsource
when I code Me.dgv_jv.DataSource = bs_jv the dgv is populated with data
while the dgv is populated, I want to check a table field "DBCR" if equal CR then I want to add 8 spaces to ACC_NAME (I know how to do that)
I tried the code below, but it seems it execute this sub 4 times although I have 2 row
Private Sub dgv_jv_RowsAdded(sender As Object, e As DataGridViewRowsAddedEventArgs) Handles dgv_jv.RowsAdded
MsgBox("e.RowIndex = " + e.RowIndex.ToString + vbCrLf + "dgv_jv.RowCount = " + dgv_jv.RowCount.ToString)
End Sub
I can create a variable to make this sub executed once, or i can loop through rows and do my changes
is there a datagridview event that will catch rows insert only once?
2 answers
Sort by: Most helpful
-
-
Karen Payne MVP 35,196 Reputation points
2021-01-19T13:08:25.04+00:00 Hello,
One way to achieve this is to setup the DataGridView with a DataSource using a BindingList and BindingSource and subscribe to DataSourceChanged event of the BindingSource.
Full source
In the example below the following class represents the container for displaying, adding, editing and deleting in the DataGridView. Note INotifyPropertyChanged provides the ability for the DataGridView to be notified of changes and reflect this visually. The code in Person class may seem like a lot but it's worth the effort.
Container
Imports System.ComponentModel Imports System.Runtime.CompilerServices Public Class Person Implements INotifyPropertyChanged Private _firstName As String Private _lastName As String Private _personId As Integer Public Property PersonId() As Integer Get Return _personId End Get Set _personId = Value OnPropertyChanged() End Set End Property Public Property FirstName() As String Get Return _firstName End Get Set _firstName = Value OnPropertyChanged() End Set End Property Public Property LastName() As String Get Return _lastName End Get Set _lastName = Value OnPropertyChanged() End Set End Property Public Event PropertyChanged As PropertyChangedEventHandler _ Implements INotifyPropertyChanged.PropertyChanged Protected Overridable Sub OnPropertyChanged( <CallerMemberName> Optional memberName As String = Nothing) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(memberName)) End Sub Public Overrides Function ToString() As String Return $"{PersonId} {FirstName} {LastName}" End Function End Class
Load
Here I use mocked data
Public Class DataOperations Public Shared Function LoadPeople() As List(Of Person) Return New List(Of Person) From { New Person() With {.PersonId = 1, .FirstName = "Karen", .LastName = "Payne"}, New Person() With {.PersonId = 2, .FirstName = "Bill", .LastName = "Miller"}, New Person() With {.PersonId = 3, .FirstName = "Anne", .LastName = "Adams"}} End Function End Class
Form code
Here DataSourceChanged is fired when personBindList = New BindingList(Of Person)(peopleList) is called. I check for FirstName equal to Karen and change it.
Imports System.ComponentModel Public Class Form1 Private personBindList As New BindingList(Of Person) WithEvents personBindingSource As New BindingSource Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown PeopleDataGridView.AutoGenerateColumns = False Dim peopleList = DataOperations.LoadPeople() personBindList = New BindingList(Of Person)(peopleList) personBindingSource.DataSource = personBindList PeopleDataGridView.DataSource = personBindingSource End Sub Private Sub personBindingSource_DataSourceChanged(sender As Object, e As EventArgs) _ Handles personBindingSource.DataSourceChanged For index As Integer = 0 To personBindList.Count - 1 If personBindList(index).FirstName = "Karen" Then personBindList(index).FirstName = "Karen 1" End If Next End Sub End Class
In closing
If you are using a DataTable as the DataSource for the BindingSource the above will still work without the Person class as DataSourceChanged event will still be triggered.