Trouble with DGV and DataRow

Sep 11, 2008 at 6:15 PM
Edited Sep 11, 2008 at 6:22 PM
Hi all.

I have a DGV that is bound to a datatable. The table's rows are populated with a simple custom class object (I mean really simple - one string property called "Value") that is hooked up to the UndoRedoManager (by having the private member as UndoRedo (Of String) ).  What I want to do is have the undo/redo functionality on a cell-by-cell basis within a datagridview.  When the custom class is represented within a collection everything works great (and I love how this library works!), however when I have the extra layer of the datatable and datarow there is an issue with type conversion.  I receive a FormatException where there is an invalid cast between String and my class type.

Half the problem has been solved by implementing a custom TypeConverter class and setting it to the TypeConverter attribute of my class.  This allows me to write changes to my "Value" property, but when I try to call the Undo() method the FormatException rears it's ugly head again.

For the sake of seeing what I'm doing here is the code I am working with...


GetType(CellConverter))> _
Public Class Cell

m_value As New UndoRedo(Of String)("")
Public Property Value() As String 
Return m_value.Value
End Get 
Set(ByVal value As String
m_value.Value = value
End Set 
End Property 

Sub New(ByVal strValue As String
Value = strValue
End Sub 

Overrides Function ToString() As String 
Return m_value.Value 
End Function
End Class

Public Class CellConverter
Inherits System.ComponentModel.TypeConverter
Public Overloads Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
If sourceType Is GetType(String) Then 
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function

Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
If destinationType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertTo(context, destinationType)
End Function

Public Overloads Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
If TypeOf value Is String Then
Return New Cell(value)
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function

Public Overloads Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
If destinationType Is GetType(String) Then
Return CType(value, Cell).Value
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function

End Class




...I believe the issue stems from within the TypeConverter's ConvertFrom member because I am returning a new Cell object (which does not retain the same private variable that is being tracked from within the UndoRedoManager.  unfortunately there is no way to reliably point to the actual Cell object in this converter -- the "context" argument has an Instance property that can point to the instance of Cell...  but it cannot be trusted and is always equal to Nothing (null) in my tests.

So here are my questions:

  1. Can anyone explain why my TypeConversion is failing with an UndoRedo implementation (it works fine if there is no implementation -- but then there is no Undo happening to throw a monkey wrench in there either)?
  2. Is there a way to pass a reference to the private member in my class to a new instance of teh class and still have it work -- this seems to be the only workaround I can think of?
  3. Am I just way off-base and shoudl I be doing something differently?


Sep 13, 2008 at 3:13 AM
After a lot more experimentation I can see that the invalid cast exception stemming from the DGV formatting attempt is happening at a point in the stack that is internal to the DGV control.  I think my only option is to run the DGV in Virtual Mode which places the onus on me to provide the parsing and formatting between the DGV cell contents and my underlying class (i.e I manage my own data store and pass the string values back and forth between it and the cells when needed.  I was trying to avoid that to see if I could figure out the puzzle of it but I think it's a losing battle at this point.  I'm certain that Virtual Mode will do what I need.

However, I think this exercise brings up an interesting point and potentially of value to DejaVu's development -- are there cases when a private UndoRedo<> member in a class can or should be passed on (including its history of edits) to a member in another reference object?  This seems like an extention of the Copy() function found in many reference classes except that there is more currency to be passed along with an edit history.

Sergei -- thanks for contacting me and offering to look into this, but I think the issue may be too far out of the scope of your library to be of use to DejaVu's development.  Your choice though.  Again, thanks.