My example does one row at a time. This is good if you do row validation with the RowValidating event. Assume my code fires off in the RowValidating event. (m_ds is my DataSet that is attached to my grid)
*This is inside of the Row Validating event {
If m_ds.HasChanges then
         GetUserChanges()
End if
}
    ''' <summary>
   
'''This code will go through and get all
original values from the row and/or the new ones depending on what time of
RowState the
   
''' row is in. 
These values are retrieved before changes are committed to the dataset
with the m_ds.update statement
   
''' </summary>
   
''' <remarks>jefz</remarks>
   
Private Sub
GetUserChanges()
        Dim
dtChanges As New
DataTable
        Dim
dtRow As DataRow
        Dim
strOriginalValue As String
= ""
        Dim
strNewValue As String
= ""
        Dim
strType As String
= ""
        Try
            'check to
see what kind of changes were made to the DataSet: Modified, Added, or Deleted
            If
m_ds.HasChanges(DataRowState.Modified) Then
                dtChanges =
m_ds.Tables.Item(0).GetChanges(DataRowState.Modified)
                strType = "M"
            ElseIf
m_ds.HasChanges(DataRowState.Added) Then
                dtChanges =
m_ds.Tables.Item(0).GetChanges(DataRowState.Added)
                strType = "A"
            ElseIf
m_ds.HasChanges(DataRowState.Deleted) Then
                dtChanges =
m_ds.Tables.Item(0).GetChanges(DataRowState.Deleted)
                strType = "D"
            Else
                Throw
New Exception("No changes were found ... Should not be trying to
save")
            End
If
            dtRow = dtChanges.Rows(0)
            Select
Case strType
                'if
the row was modified then get the original value as well as the new value from
the dataset
                Case
"M"
                    For
Each Column As DataColumn In
dtChanges.Columns
                        strOriginalValue =
dtRow(Column, DataRowVersion.Original).ToString
                        strNewValue =
dtRow(Column, DataRowVersion.Current).ToString
                    Next
                    'if
the row was added then you can only get the new values
                Case
"A"
                    For
Each Column As DataColumn In
dtChanges.Columns
                        strNewValue =
dtRow(Column, DataRowVersion.Current).ToString
                    Next
                    'if
is going to be deleted then you can only get the old rows
                Case
"D"
                    For
Each Column As DataColumn In
dtChanges.Columns
                        strOriginalValue =
dtRow(Column, DataRowVersion.Original).ToString
                    Next
                Case
Else
                    Throw
New Exception("No changes were found ... Should not be trying to
save")
            End
Select
        Catch
ex As Exception
            Throw
ex
        End Try
   
End Sub
You can do whatever you want with the values within the select case or if you want to store these values for later use, instead of storing their values into a string variable, you can add them to an array or collection.
