TreeView Drag & Drop help - _Invalid FORMATETC structure_ exception

3

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)

c#
.net
winforms
asked on Stack Overflow Sep 8, 2008 by mikeymo

3 Answers

3

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;
    }
answered on Stack Overflow May 12, 2012 by Steve Cadwallader
1

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.

  1. Remove the original tree structure and destination. Dump your dlls. Close everything. Open up and put the treeview and destination back on the form. It may have just been poorly formed and not fully populating the FORMATETC structure.
  2. Try putting another treeview and droping to that. If you are droping to another tree and it works you know your oranges to oranges work and it isn't the treeview. It may be the destination if it is a grid or listview. You may need to change those structures to be able to receive the drop.

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;
answered on Stack Overflow Sep 9, 2008 by Stradas • edited Jul 10, 2009 by Benjamin Autin
1

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.

answered on Stack Overflow Aug 22, 2009 by Joe Caffeine

User contributions licensed under CC BY-SA 3.0