Question

I'm currently writing a tool to assign entities from one DataGrid to entities in another DataGrid via drag-and-drop.
With some fiddling, I got everything to run smoothly, with one minor annoyance: Some entities cannot be assigned to some other entities, which isn't reflected by the UI (yet).

So, the behavior I want to achieve is the following: When the user drags the assignee over the other entity, the icon should change to the "you can't drop that here" icon if the entities aren't compatible.

This is my code (attached to the DataGridDragDropTarget.DragOver event of the target DataGrid):

private void DragDropTarget_OnDragOver(object sender, Microsoft.Windows.DragEventArgs e)
{
    var sw = sender as DataGridDragDropTarget;

    if (sw == null)
    {
        return;
    }

    if(GetAssignmentCondition(e))
    {
        // TODO: Show link-icon
    }
    else
    {
        // TODO: Show drop-disabled-icon
    }
}

What I've tried so far:

I've set e.Effects, the DragDropTarget's AllowedSourceEffects property and the underlying ItemDragEventArgs's AllowedEffects and Effects to DragDropEffects.None, to no avail. Googling also didn't yield any meaningful results, and I'm out of ideas.

Was it helpful?

Solution

This helps in situations with TextBox and FlowDocument controls, so it should work with DataGrid.

The key here is to set the event to Handled to keep the control from doing its shenanigans.

Something like so:

Code behind (just for demonstration - preferably use a more MVVM friendly solution):

private void DragDropTarget_DragEnter(object sender, Microsoft.Windows.DragEventArgs e)
{
    var sw = sender as DataGridDragDropTarget;

    if (sw == null)
    {
        return;
    }

    if(GetAssignmentCondition(e))
    {
        // TODO: Show link-icon
        e.Effects = DragDropEffects.Link;
    }
    else
    {
        // TODO: Show drop-disabled-icon
        e.Effects = DragDropEffects.None;
    }

    // Add this
    e.Handled = true;
}

OTHER TIPS

Changing the Effects property of DragEventArgs in the OnDragOver event handler without setting the Handled property to 'true' does not works because as you can see here in the DragDropTarget.cs source code. If OnDragOver is not handled (args.Handled=true;) in any of event handlers, the args.Effects will revert back to args.AllowedEffects.

    protected virtual void OnDragOver(SW.DragEventArgs args)
    {
        foreach (SW.DragEventHandler handler in _dragOver)
        {
            handler(this, args);
            if (args.Handled)
            {
                return;
            }
        }

        OnDragEvent(args);
    }

    protected virtual void OnDragEvent(SW.DragEventArgs args)
    {
        SW.DragDropEffects effects = args.AllowedEffects;

        ///removed for clarity

        if (!args.Handled && effects != args.AllowedEffects)
        {
            args.Effects = effects;  // revert back to args.AllowedEffects
            args.Handled = true;
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top