0
votes

I managed to drag and drop items from my ListView onto a canvas and show an image on it. I used this question as a template: https://social.msdn.microsoft.com/Forums/en-US/cef5c42c-87a0-4e19-afc8-935284607488/drag-and-drop-controls-issue-from-listbox-into-canvas-wpf?forum=wpf

I also added the suggestion in that thread, so that the Item gets rendered where I drop it. These are the code behinds for my "Drawing Plate" (The canvas) and the ListView:

Canvas:

public partial class DrawingPlateUC : UserControl
{
    IMessenger messenger = Messenger.Instance;

    public DrawingPlateUC()
    {
        InitializeComponent();
    }

    void Canvas_Drop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("MyFormat"))
        {
            var module = e.Data.GetData("MyFormat") as Module;
            Canvas CanvasView = sender as Canvas;

            Image image = new Image();
            image.Source = module.ModuleImage;

            CanvasView.Children.Add(image);
        }
    }

    private void Canvas_DragOver(object sender, DragEventArgs e)
    {
        // write down this point to a private member
        Point enterPoint = e.GetPosition(this.moduleCanvas);

        messenger.Send<Point>(enterPoint, MessengerTopics.MousePoint);
    }

    void Canvas_DragEnter(object sender, DragEventArgs e)
    {
        if (!(e.Data.GetDataPresent("contact")) || (sender == e.Source))
        {
            e.Effects = DragDropEffects.Copy;
        }
    }
}

ListView:

public partial class ItemListViewUC : UserControl
{

    IMessenger messenger = Messenger.Instance;

    Point startPoint;
    Point enterPoint;

    public ItemListViewUC()
    {
        messenger.Register<Point>(this, MessengerTopics.MousePoint, GetEnterPoint);

        InitializeComponent();
    }

    private void GetEnterPoint(Point point)
    {
        enterPoint = point;
    }

    void StackPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        startPoint = e.GetPosition(null);
    }

    void StackPanel_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        Point mousPos = e.GetPosition(null);
        Vector diff = startPoint - mousPos;

        if ((e.LeftButton == MouseButtonState.Pressed) && (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance) && (Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
        {
            ListView listView = sender as ListView;
            ListViewItem listViewItem = FindAnchestor<ListViewItem>((DependencyObject)e.OriginalSource);
            if (listViewItem == null) { return; }
            var contact = (Module)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
            DataObject dataObject = new DataObject("MyFormat", contact);
            try
            {
                DragDrop.DoDragDrop(listViewItem, dataObject, DragDropEffects.Copy);
            }
            catch { }
            // Set the Margin property to place the drag item on the canvas.
            listViewItem.Margin = new Thickness(enterPoint.X, enterPoint.Y, 0, 0);
        }
    }

    static T FindAnchestor<T>(DependencyObject current) where T : DependencyObject
    {
        do
        {
            if (current is T)
            {
                return (T)current;
            }
            current = VisualTreeHelper.GetParent(current);
        }
        while (current != null);

        return null;
    }
}

This here is supposed to draw the Image on the spot where I dropped it:

listViewItem.Margin = new Thickness(enterPoint.X, enterPoint.Y, 0, 0);

But it only renders on the top left corner, coordinates 0, 0 of the canvas. This is for all Items I drop, they overlay on that position. I already checked the coordinates, they are not 0, 0, but the ones where my mouse is when I drop the item.

This is my Window:

enter image description here

1

1 Answers

1
votes

when you drop an item, you don't set any coordinate for Image:

void Canvas_Drop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent("MyFormat"))
    {
        var module = e.Data.GetData("MyFormat") as Module;
        Canvas CanvasView = sender as Canvas;

        Image image = new Image();
        image.Source = module.ModuleImage;
        image.SetValue(Canvas.LeftProperty, _enterPoint.X);
        image.SetValue(Canvas.TopProperty, _enterPoint.Y);

        CanvasView.Children.Add(image);
    }
}

private Point _enterPoint;
private void Canvas_DragOver(object sender, DragEventArgs e)
{
    _enterPoint = e.GetPosition(this.moduleCanvas);

    messenger.Send<Point>(_enterPoint, MessengerTopics.MousePoint);
}