0

I have a ReadOnly DataGridView bound to a bindingSource. There are other controls on the form that update the DataGridViewCells - they are databound to the bindingsource. I need to change the datagridviewCell styles based on what the DataViewRowState of the source is - .Current does not help me - what I need to do is track is the cell the original value - color the cell normal, if it is modified color it blue. I know I can get the DataRowViewState that gives me the version I am getting - but it always comes back current (as it is the default) and I do want the current - I just want to know if it differs from the original or not for this particular column. Since in my edit of the bindingsource I already have the row there does not appear to be an easy method or property that says this row is the original, or modified. Do I need to run a select using filterstates on the table to get my row and see if I get results back and then if so change the cell in order to do this ?

Relevant Code: - I know it is in VB.net but if you have c# example that is fine I do not care which - .net code is code and I can convert it.

Private Sub UpdateCellValue(columnName As String, textValue As String)

    If dgvBayList.SelectedRows.Count > 0 Then
        Dim crow As DataGridViewRow = dgvBayList.SelectedRows(0)
        Dim drv As DataRowView = DirectCast(bsBins.Current, DataRowView)

        If crow.Cells(columnName).Value = textValue Then
            Exit Sub
        End If

        drv.BeginEdit()
        drv.Row.BeginEdit()
        drv.Row.SetField(Of String)(columnName, textValue)
        ' My Problem here is of course it is always original, 
        ' the row states of the Row always show Modified. 
        ' This happens when the binding source gets filled and bound to datagridview.

        Select Case drv.RowVersion
            Case DataRowVersion.Original
                Dim val As String = drv.Row(0).ToString()
                Exit Select
            Case DataRowVersion.Proposed
                Dim val As String = drv.Row(0).ToString()
                Exit Select
            Case DataRowVersion.Current
                Dim val As String = drv.Row(0).ToString()
                Exit Select
            Case DataRowVersion.Default
                Dim val As String = drv.Row(0).ToString()
                Exit Select
        End Select
        crow.Cells(columnName).Value = textValue
        drv.Row.EndEdit()
        drv.EndEdit()
        Dim dt As DataTable = sortingDataSet.bins

    End If

End Sub
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
Ken
  • 2,518
  • 2
  • 27
  • 35
  • 1
    It seems that you need drv.Row.RowState not drv.RowVersion – Steve Aug 18 '16 at 15:42
  • @Steve my RowState is always modified even before modification; I do not know why it is like this. The binding source is bound to a dataset.Table which gets filled on form load. Since it always declares modified from the get go - that does not help me. I also need to know if user changed it back to original - I want it to look like a normal unchanged cell. I am thinking I am going to need to select using rowfilter - there should be an easier way. I hope there is one. – Ken Aug 18 '16 at 15:48
  • If I look at `RowState` in the cell formatting event, it works fine for me. – Ňɏssa Pøngjǣrdenlarp Aug 18 '16 at 15:57
  • @Plutonix - when I look at it in cell formatting event it shows rowstate modified - my binding source rows show modified (all I have done is load the datagridview from a dataset and nothing more), if the form user changes the value back - it should not say modified either. I am programatically editing directly in the bindingsource datasource and not in the datagridview. However I have found this http://stackoverflow.com/questions/1050837/how-can-i-get-a-specific-version-of-a-dataset-row which might be of some help - I can compare original with current. – Ken Aug 18 '16 at 18:09

1 Answers1

0

After looking at the comments and using different thoughts to search I found a SO answer that provided part of the solution How can I get a specific version of a dataset row?.

In order to implement that solution , I needed to set up a mechanism for calling a generic function where T was unknown until run time. After looking again on SO - I found some good answers for that; How do I use reflection to call a generic method? .

Below is the final code I use From my controls changed value to implement the changes to the datagridview and apply styles to the individual cells based on Original or Proposed values.

Private Sub UpdateCellValue(Of T)(columnName As String, value As T)

    If dgvBayList.SelectedRows.Count > 0 Then

        Dim crow As DataGridViewRow = dgvBayList.SelectedRows(0)

        Dim drv As DataRowView = DirectCast(bsDataSource.Current, DataRowView)

        If crow.Cells(columnName).Value = value Then
            Exit Sub
        End If

        drv.BeginEdit()

        drv.Row.BeginEdit()

        drv.Row.SetField(Of T)(columnName, value)

        crow.Cells(columnName).Value = value

        Dim objType As Type = drv.Row(columnName).GetType()

        Dim method As Reflection.MethodInfo = _
                 Me.GetType().GetMethod("SetDataGridViewCellStyle", _
                 Reflection.BindingFlags.Instance Or _ 
                 Reflection.BindingFlags.NonPublic Or _
                 Reflection.BindingFlags.Public)

        Dim GenericSetDataGridViewCellStyle As Reflection.MethodInfo = _
                                               method.MakeGenericMethod(objType)

        Dim parms As Object() = {crow.Cells(columnName), drv, columnName}

        GenericSetDataGridViewCellStyle.Invoke(Me, parms)

        drv.Row.EndEdit()
        drv.EndEdit()
    End If

End Sub

Private Sub SetDataGridViewCellStyle(Of T) ( _
                             cell As DataGridViewCell, _
                             dRowView As DataRowView, _ 
                             columnName As String)

    Dim nothingness As Integer = 0

    If dRowView.Row.Field(Of T)(columnName, DataRowVersion.Original) Is Nothing Then
        nothingness += 1
    End If

    If dRowView.Row.Field(Of T)(columnName, DataRowVersion.Current) Is Nothing Then
        nothingness += 1
    End If

    If nothingness = 0 Then

        Dim original As T = dRowView.Row.Field(Of T)(columnName, DataRowVersion.Original)
        Dim current As T = dRowView.Row.Field(Of T)(columnName, DataRowVersion.Current)
        Dim proposed As T = dRowView.Row.Field(Of T)(columnName, DataRowVersion.Proposed)

        If EqualsCompare(Of T)(original, proposed) Then   

            cell.Style.BackColor = Color.FromKnownColor(KnownColor.White)

        Else

            cell.Style.BackColor = Color.FromKnownColor(KnownColor.Fuchsia)

        End If

    Else
        If nothingness = 2 Then

            cell.Style.BackColor = Color.FromKnownColor(KnownColor.White)
        Else
            ' cell.Style.BackColor = Color.FromKnownColor(KnownColor.Fuchsia)'
        End If

    End If

    cell.DataGridView.Update()

End Sub

Public Shared Function EqualsCompare(Of T)(a As T, b As T) As Boolean

    Return EqualityComparer(Of T).[Default].Equals(a, b)

End Function

And I call it like this

UpdateCellValue(Of Boolean)("kickingIt", True)

Relevant links that helped me

How can I get a specific version of a dataset row?

How do I use reflection to call a generic method?

Community
  • 1
  • 1
Ken
  • 2,518
  • 2
  • 27
  • 35