James Carlyle-Clarke
James Carlyle-Clarke

Reputation: 868

Limit drag and drop to within a single control

I've looked and looked and can't find an answer.

I have a TreeView. It has Drag and Drop to allow moving of Nodes within the tree.

I want to limit the drag and drop to only work within that one control, within a single instance of the application (the application itself can run more than one instance).

I've tried the following:

private void SubFolderTreeView_DragEnter(object sender, DragEventArgs e)
{
    TreeView source = sender as TreeView;    // also tried = (TreeView) sender;

    if (source == this.SubFolderTreeView && e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
        e.Effect = DragDropEffects.Move; // Okay, set the visual effect
    else
        e.Effect = DragDropEffects.None; // Unknown data, ignore it
}

Unfortunately, a second instance of the same application will still be able to drag from its TreeView to the first TreeView: (source == this.SubFolderTreeView) is true

I have not tested if a totally different treeview could drag to mine, though I doubt it, but the above behaviour is already a fail.

I tried some other things - comparing the form or the control's handle also didn't work

bool isSameForm = ((MyForm) source.TopLevelControl == this);    // still true
bool isSameHandle = (((Control)source).Handle == ((Control)this.SubFolderTreeView).Handle);     // still true

The only other things I can think of, off the top of my head, is a random number stored in the TreeView or Form (probably won't work), and checking the absolute screen position of the control (not the best method).

I could of course stick a mutex in the application and so only allow one instance to run, but I'd rather not.

Can anyone suggest a good way of doing this?

Upvotes: 3

Views: 2889

Answers (2)

James Carlyle-Clarke
James Carlyle-Clarke

Reputation: 868

To flesh out Hans Passant's solution (which worked perfectly, thanks Hans) for future reference and other searchers into this problem, I used the code:

// prevents dragging from other instances of this form - thanks to Hans Passant
private bool DragDropFromThisForm = false;

private void SubFolderTreeView_ItemDrag(object sender, ItemDragEventArgs e)
{
    // Initiate drag/drop
    DragDropFromThisForm = true;
    DoDragDrop(e.Item, DragDropEffects.Move);
    DragDropFromThisForm = false;
}

private void SubFolderTreeView_DragEnter(object sender, DragEventArgs e)
{
    MyForm form = (MyForm) (sender as TreeView).TopLevelControl;

    if (form.DragDropFromThisForm && e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
        e.Effect = DragDropEffects.Move; // Okay, set the visual effect
    else
        e.Effect = DragDropEffects.None; // Unknown data, ignore it
}

It may well be that DJ Kraze's answer would also work, and perhaps be a tad more elegant, but Hans' solution is lightweight and effective.

Upvotes: 2

Greg B
Greg B

Reputation: 426

I'm not really following the restrictions, seems like flawed logic with the information you've given (all identical instances, but only one can have drag and drop - what??), but some suggestions:

  • Have a property that determines whether nodes can 'drag and drop' and only set it in the one instance.
  • Only subscribe to the event on the one instance that you want to be able to 'drag and drop' on.
  • Create a separate TreeView class that supports dragging and dropping, and instantiate the base TreeView everywhere else.

Upvotes: 1

Related Questions