Using a subclassed DataObject as Clipboard DataObject

1.2k Views Asked by At

When I try the following the results are unexpected. Any ideas will be most appreciated!

    Class DataObjectSub
        Inherits DataObject

    End Class

    Sub Test()

        Dim myObject = New DataObjectSub

        myObject.SetData("Test")
        Clipboard.SetDataObject(myObject)

        Dim myRetrievedObject As IDataObject = Clipboard.GetDataObject
        Console.Write(myRetrievedObject.GetType.ToString)

        Dim myRetrievedObject2=TryCast(Clipboard.GetDataObject,DataObjectSub)

    End Sub

myRetrievedObject2 is Nothing

The output of the Write statement is: "System.Windows.Forms.DataObject". Shouldn't it be "DataObjectSub"? Am I missing something obvious?

Edited as requested:

In the case of Drag/Drop operations, that DataObject (implementing iDataObject) is again being used one can do this:

Sub TestDragDrop

Dim myObject as iDataObject=new DataObjectSub

someControl.DoDragDrop(myObject, myAllowedEffects)

End Sub

Later... in a DragOver event handler:

Sub anotherControl_DragOver(sender as object, e as DragEventArgs)

Dim myRetrievedObject1 as DataObjectSub = TryCast(e.Data, DataObjectSub)
Dim myRetrievedObject2 as IDataObject = e.Data


End Sub

works well and both myRetrievedObject1 and myRetrievedObject2 are not Nothing. The types of both retrieved objects are DataObjectSub.

Thanks for any ideas and patience! :)

1

There are 1 best solutions below

1
On

This is not an unexpected behaviour. Clipboard.GetDataObject just stores the data in the Clipboard (as referred by MSDN) and its type is DataObject (as referred by your code). When you check its type, is irrelevant whether the input variable is DataObject or any other type (supported by GetDataObject). Bear in mind that GetDataObject is a method, whose returned value does not need to follow the default assignation rules (i.e., calling it does not provoke the same effects than assigning a String variable to an Object variable, for example).

This code:

Dim myString As String = "Test"
Clipboard.SetDataObject(myString)
Dim myRetrievedObject As IDataObject = Clipboard.GetDataObject
Console.Write(myRetrievedObject.GetType.ToString)

outputs exactly the same result than your code. myRetrievedObject.GetType.ToString just checks the type of GetDataObject, which is always DataObject.

UPDATE

After our discussion, I want to clarify that Clipboard.GetDataObject returns a IDataObject variable (the interface of DataObject, not a different type). Sample code to understand all this:

Dim myRetrievedObject1 As IDataObject = Clipboard.GetDataObject
Dim myRetrievedObject2 As DataObject = New DataObject(Clipboard.GetDataObject)
Dim myRetrievedObject3 As DataObject = DirectCast(Clipboard.GetDataObject, DataObject)
Dim test4 As DataObject = New DataObject

If (TypeOf myRetrievedObject1 Is DataObject AndAlso TypeOf myRetrievedObject2 Is DataObject AndAlso TypeOf myRetrievedObject3 Is DataObject AndAlso TypeOf test4 Is DataObject) Then
    'Condition is met
End If
If (TypeOf myRetrievedObject1 Is IDataObject AndAlso TypeOf myRetrievedObject2 Is IDataObject AndAlso TypeOf myRetrievedObject3 Is IDataObject AndAlso TypeOf test4 Is IDataObject) Then
    'Condition is met
End If

As you can see (the two conditions are met, what means that all the variables are of type DataObject and IDataObject at the same time), the relationship DataObject/IDataObject is not like the one between two different types. Actually, as shown by myRetrievedObject3, the casting is a mere formal requirement (I am casting a DataObject variable to DataObject!). DataObject/IDataObject are basically two sides of the same coin (which is called DataObject). This implies that the condition below is true:

Dim Type1 As String = myRetrievedObject1.GetType().ToString()
Dim Type2 As String = myRetrievedObject2.GetType().ToString()
Dim Type3 As String = myRetrievedObject3.GetType().ToString()
Dim Type4 As String = test4.GetType().ToString()

If (Type1 = Type2 AndAlso Type1 = Type3 AndAlso Type1 = Type4 AndAlso Type1 = GetType(DataObject).ToString) Then
    'Condition is met
End If

That is, the type name for both DataObject and IDataObject variables is DataObject (or, more precisely: System.Windows.Forms.DataObject).