I'm trying to implement Drag & Drop functionality with source being a TreeView control. When I initiate a drag on a node, I'm getting:
Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))
The ItemDrag handler (where the exception takes place), looks like:
private void treeView_ItemDrag(object sender,
System.Windows.Forms.ItemDragEventArgs e)
{
this.DoDragDrop(e.Item, DragDropEffects.Move);
}
Does anyone know the root cause of this and how to remedy it? (.NET 2.0, Windows XP SP2)
In case it helps anyone else - I encountered this problem with the WPF TreeView (not Windows Forms as listed in the question) and the solution was simply to make sure to mark the event as handled in the drop event handler.
private void OnDrop(object sender, DragEventArgs e)
{
// Other logic...
e.Handled = true;
}
FORMATETC
is a type of application clipboard, for lack of a better term. In order to pull off some of the visual tricks of draging around the tree node, it has to be copied into this clipboard with its source description. The source control loads its info into the FORMATETC
clipboard and sends it to the target object. It looks like the error occurs on the drop and not on the drag. The DV
in DV_E_FORMATETC
typically indicates the error occurrs on the drop step.
The destination doesn't look like it likes what you are droping on it. The clipboard may be corrupt or the drop destination may not be configured to understand it.
I recommend you try one of two things.
FORMATETC
structure.Not that it helps but the structure is something like this:
typedef struct tagFORMATETC
{
CLIPFORMAT cfFormat;
DVTARGETDEVICE *ptd;
DWORD dwAspect;
LONG lindex;
DWORD tymed;
} FORMATETC, *LPFORMATETC;
When doing drag and drop with list and treeview controls you have to make sure that you removing and inserting the list items correctly. For example, using drag and drop involving three ListView controls:
private void triggerInstanceList_DragOver(object sender, DragEventArgs e)
{
SetDropEffect(e);
}
private void triggerInstanceList_DragEnter(object sender, DragEventArgs e)
{
SetDropEffect(e);
}
private void SetDropEffect(DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListViewItem)))
{
ListViewItem itemToDrop = e.Data.GetData(typeof(ListViewItem)) as ListViewItem;
if (itemToDrop.Tag is TriggerTypeIdentifier)
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.Move;
}
else
e.Effect = DragDropEffects.None;
}
private void triggerInstanceList_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListViewItem)))
{
try
{
ListViewItem itemToDrop = e.Data.GetData(typeof(ListViewItem)) as ListViewItem;
if (itemToDrop.Tag is TriggerTypeIdentifier)
{
ListViewItem newItem = new ListViewItem("<new " + itemToDrop.Text + ">", itemToDrop.ImageIndex);
_triggerInstanceList.Items.Add(newItem);
}
else
{
_expiredTriggers.Items.Remove(itemToDrop);
_triggerInstanceList.Items.Add(itemToDrop);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
you will note that at the end of the DragDrop event I am either moving the ListViewItem or creating a copy of one.
User contributions licensed under CC BY-SA 3.0