Drag&Drop ed ereditarietà

Sarà un bug dell'oggetto System.Windows.Forms.DataObject?

Dal principio: ho una treeview che contiene oggetti di tipo System.Windows.Forms.TreeNode ed oggetti di tipo treeNode che ereditano, naturalmente, dal primo tipo.
Quando parte un Drag&Drop chiamo la DoDragDrop con il nodo in questione:
Me.DoDragDrop(e.Item, AllowDrag)

All'evento DragOver verifico la presenza di un oggetto di tipo System.Windows.Forms.TreeNode in e.Data:
If e.Data.GetDataPresent(GetType(System.Windows.Forms.TreeNode)) Then
Purtroppo questo metodo ritorna true SOLO nel caso che l'oggetto sia effettivamente di tipo System.Windows.Forms.TreeNode e non se questo é un tipo da lì ereditato!!!

Soluzioni?
Nulla, quindi mi armo di Reflector ed indago:
Innanzitutto e.Data a parte l'interfaccia IDataObject é di tipo System.Windows.Forms.DataObject il quale contiene un campo privato che si chiama InnerData del tipo privato System.Windows.Forms.DataObject.DataStore.
System.Windows.Forms.DataObject.DataStore ha un campo privato di nome data e tipo HashTable. All'interno di tale hashtable vengono immaginazzinati oggetti di tipo (privato ovviamente) System.Windows.Forms.DataObject.DataStore.DataStoreEntry il quale tipo contiene un campo (gioite: questo é publico! ) di nome data che contiene effettivamente l'oggetto che abbiamo passato alla DoDragDrop.

Quindi, eccovi l'inguardabile soluzione:

Private Shared DataObject_innerDataFI As System.Reflection.FieldInfo = _
  GetType(System.Windows.Forms.DataObject).GetField("innerData", Reflection.BindingFlags.NonPublic 
Or Reflection.BindingFlags.Instance)
Private Shared DataStoreType As System.Type = _
  GetType(System.Windows.Forms.DataObject).GetNestedType("DataStore", Reflection.BindingFlags.NonPublic)
Private Shared DataStore_dataFI As System.Reflection.FieldInfo = _
  DataStoreType.GetField("data", Reflection.BindingFlags.NonPublic 
Or Reflection.BindingFlags.Instance)
Private Shared DataStoreEntryType As System.Type = _
  DataStoreType.GetNestedType("DataStore", Reflection.BindingFlags.NonPublic)
Private Shared DataStoreEntry_dataFI As System.Reflection.FieldInfo = _
  DataStoreType.GetField("data", Reflection.BindingFlags.NonPublic 
Or Reflection.BindingFlags.Instance)

Protected Overridable Function GetData(ByVal Data As System.Windows.Forms.DataObject, ByVal type As System.TypeAs Object
  
'System.Windows.Forms.DataStore é un tipo privato!
  
Dim DataStore As Object = DataObject_innerDataFI.GetValue(Data)

  
Dim hash As Hashtable = DirectCast(DataStore_dataFI.GetValue(DataStore), Hashtable)

  
For Each DI As System.Collections.DictionaryEntry In hash
    
Dim Value As Object = DataStoreEntry_dataFI.GetValue(DI.Value)
    
If type.IsInstanceOfType(Value) Then
      Return 
Value
    
End If
  Next 
DI
End Function

GetData vi ritornerà l'oggetto di tipo Type contenuto nel DataObject passato!

...Ora me ne vado a casa a sciacquarmi gli occhi, buon weekend a tutti!!!

Print | posted on venerdì 28 gennaio 2005 20:43

Comments have been closed on this topic.