Data.GetData(...) when exact type is not known?

  • Thread starter Thread starter Andy
  • Start date Start date
A

Andy

I'm making a drag and drop application, and in the *_DragDrop(...)-method I
have the following code:

private void SelectTree_DragDrop(object sender,
System.Windows.Forms.DragEventArgs e)
{
Object item = (object)e.Data.GetData(typeof(AbstractNode));
// Other code
}

My problem is that the type inside the brackets of typeof(...) is not
AbstractNode, instead the type can be a varity of types which all are
inherited from AbstractNode, i e I have a lot of node classes that all
inherits from the class AbstractNode.

How do I handle this problem? Of course, I don't want to handle every type
with some if statement.
 
Andy,

The drag and drop operation should use serialization, so you should be
able to get the specific type by calling the GetType method on the item
parameter.

However, you should really cast this to a base class, or an interface
implmentation which has the contract defined for the functionality that you
wish to execute. This way, you don't have to make specific casts to
specific types.

Hope this helps.
 
The drag and drop operation should use serialization, so you should be
able to get the specific type by calling the GetType method on the item
parameter.

Sorry, I don't really understand what you mean. If I don't know the type,
how do I use the GetData(...)?
Would you please give a short example?
However, you should really cast this to a base class, or an interface
implmentation which has the contract defined for the functionality that you
wish to execute. This way, you don't have to make specific casts to
specific types.

This I understand!
 
Andy,

I think I see what you mean now. Basically, the clipboard places the
specific type into the clipboard, and you don't know what that type is on
the way out.

To get around this, I would create a structure with a reference to your
type, like this:

[Serializable]
public struct AbstractNodeWrapper
{
public AbstractNode Node;
}

Then, instead of placing an instance of your abstract node on the
clipboard, create an instance of this, set the Node field to the node, and
then pass that to the DoDragDrop method.

Then, in your handler, get this structure from the GetData method, and
then call the methods you need to on the Node property.
 
[Serializable]
public struct AbstractNodeWrapper
{
public AbstractNode Node;
}

Then, instead of placing an instance of your abstract node on the
clipboard, create an instance of this, set the Node field to the node, and
then pass that to the DoDragDrop method.

Then, in your handler, get this structure from the GetData method, and
then call the methods you need to on the Node property.

Well, this would work I think, though it's a little bit ugly.

Though I find it a little hard to accept that it doesn't work directly. I
mean, say that the data is of type MyNode which is inherited from
AbstractNode, then data also should be of type AbstractNode.

I tried this, which works, but it's too ugly:

private void SelectTree_DragDrop(object sender,
System.Windows.Forms.DragEventArgs e)
{
string type = e.Data.GetFormats().GetValue(1).ToString();
AbstractNode node = (AbstractNode) e.Data.GetData(type);

// Other code
}
 
Andy,

The problem with the way you have it is that if you place more than one
type of format on the clipboard, then you might not be guaranteed that you
will be getting that format back when you get the data from the drag drop
operation. The clipboard is designed in such a way that you can get
multiple formats for the same data, so that different applications can
handle it. For example, if you place XHTML on the clipboard, it will
indicate that there is XML, HTML, and text on the clipboard, and the
application can look for a specific type and use whichever best suits its
needs.

Now, when you place the type directly on the clipboard, it is
serializing the type, and the format that it is placing on the clipboard is
the name of the type, not of the root type that it derives from. This is
why using typeof(AbstractNode) when trying to retrieve the data fails.

When you use the structure, the data is serialized to the field, and the
type that is placed on the clipboard is consistent. It's cleaner than the
way that you use, since you are guaranteed a type of that format (and aren't
just taking a stab at the first format that is on the clipboard).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Andy said:
[Serializable]
public struct AbstractNodeWrapper
{
public AbstractNode Node;
}

Then, instead of placing an instance of your abstract node on the
clipboard, create an instance of this, set the Node field to the node,
and
then pass that to the DoDragDrop method.

Then, in your handler, get this structure from the GetData method,
and
then call the methods you need to on the Node property.

Well, this would work I think, though it's a little bit ugly.

Though I find it a little hard to accept that it doesn't work directly. I
mean, say that the data is of type MyNode which is inherited from
AbstractNode, then data also should be of type AbstractNode.

I tried this, which works, but it's too ugly:

private void SelectTree_DragDrop(object sender,
System.Windows.Forms.DragEventArgs e)
{
string type = e.Data.GetFormats().GetValue(1).ToString();
AbstractNode node = (AbstractNode) e.Data.GetData(type);

// Other code
}
 
Back
Top