AJ Richardson
AJ Richardson

Reputation: 6830

WPF DragDropEffects not set properly in Drop event

I'm trying to drag-and-drop some data within my application. I want the DragDropEffects to be Move if the control key is NOT pressed, and Copy if the control key is pressed. It seems like this should be trivial, but I've searched a bunch and haven't found an answer to this.

Here is my code, based loosely on Microsoft's example:

private static void dragSource_MouseMove(object sender, MouseEventArgs e)
{
    DragDrop.DoDragDrop(currentDragDef.DragSource, currentDragDef.Data, DragDropEffects.All);
    e.Handled = true;
}

private static void dropTarget_DragOver(object sender, DragEventArgs e)
{
    bool ctrlKey = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
    if ((e.Effects & DragDropEffects.Move) == DragDropEffects.None || ctrlKey)
    {
        // Control key is pressed or move is not allowed. Do copy/link.
        e.Effects &= ~DragDropEffects.Move;
    }
    else
    {
        // Control key not pressed. Do move.
        e.Effects &= (DragDropEffects.Move | DragDropEffects.Scroll);
    }
    e.Handled = true;
}

e.Effects is getting set fine in dropTarget_DragOver. The mouse cursor adds a '+' icon whenever I press control. However, in the Drop event, e.Effects equals DragDropEffects.All again. Why is this? How to I get e.Effects to equal something different in the Drop event? Or is this even possible?

private static void dropTarget_Drop(object sender, DragEventArgs e)
{
    if (e.Effects == DragDropEffects.None || !e.Data.GetDataPresent(DataFormats.FileDrop))
        return;
    var effects = e.Effects;
    // effects == DragDropEffects.All, but I want it to have the Move or Copy flag removed
}

Aside: another thing is that I'm using Keyboard.IsKeyDown instead of e.KeyStates because e.KeyStates seems to always equal DragDropKeyStates.LeftMouseButton. The DragDropKeyStates.ControlKey bit is always 0, even if control is pressed. Any idea why this is?

Upvotes: 2

Views: 1567

Answers (1)

Phil Jollans
Phil Jollans

Reputation: 3769

You should duplicate the logic in your DragOver function in the Drop function, to determine the effects again.

Instead of reading the effects field from DragEventArgs, you should write it back. The value is passed back to the source and is the return value from the function DoDragDrop.

This is more or less described by Microsoft in https://msdn.microsoft.com/en-us/library/ms742859%28v=vs.100%29.aspx, but the behaviour is not obvious. I made the same mistake as you.

Upvotes: 3

Related Questions