C#在Canvas中拖放图像

我试图谷歌如何在canvas上拖放UIElements,但找不到我正在寻找的东西。

我有一个带有Window的C#WPF应用程序。 在窗口内我有一个Canvas,我可以在其中添加图像。 我想要的是能够拖放图像,同时保持在canvas的边界内。 我也希望它在代码中,所以不在xaml中。

我在我添加/更新图像到canvas的function中得到了这个。 TODO应该替换为拖放事件。

Image img = ImageList[i].Image; img.Name = "Image" + i; // TODO: Drag and Drop event for Image // TODO: Check if Left and Top are within Canvas (minus width / height of Image) Canvas.SetLeft(img, Left); // Default Left when adding the image = 0 Canvas.SetTop(img, Top); // Default Top when adding the image = 0 MyCanvas.Children.Add(img); OnPropertyChanged("MyCanvas"); 

PS:虽然这是为了以后,如果有人有代码一次拖放多个图像作为额外的奖励,我会很感激。

在此先感谢您的帮助。

通过使用以下代码修复了我的问题:

 img.AllowDrop = true; img.PreviewMouseLeftButtonDown += this.MouseLeftButtonDown; img.PreviewMouseMove += this.MouseMove; img.PreviewMouseLeftButtonUp += this.PreviewMouseLeftButtonUp; private object movingObject; private double firstXPos, firstYPos; private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // In this event, we get the current mouse position on the control to use it in the MouseMove event. Image img = sender as Image; Canvas canvas = img.Parent as Canvas; firstXPos = e.GetPosition(img).X; firstYPos = e.GetPosition(img).Y; movingObject = sender; // Put the image currently being dragged on top of the others int top = Canvas.GetZIndex(img); foreach (Image child in canvas.Children) if (top < Canvas.GetZIndex(child)) top = Canvas.GetZIndex(child); Canvas.SetZIndex(img, top + 1); } private void PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Image img = sender as Image; Canvas canvas = img.Parent as Canvas; movingObject = null; // Put the image currently being dragged on top of the others int top = Canvas.GetZIndex(img); foreach (Image child in canvas.Children) if (top > Canvas.GetZIndex(child)) top = Canvas.GetZIndex(child); Canvas.SetZIndex(img, top + 1); } private void MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && sender == movingObject) { Image img = sender as Image; Canvas canvas = img.Parent as Canvas; double newLeft = e.GetPosition(canvas).X - firstXPos - canvas.Margin.Left; // newLeft inside canvas right-border? if (newLeft > canvas.Margin.Left + canvas.ActualWidth - img.ActualWidth) newLeft = canvas.Margin.Left + canvas.ActualWidth - img.ActualWidth; // newLeft inside canvas left-border? else if (newLeft < canvas.Margin.Left) newLeft = canvas.Margin.Left; img.SetValue(Canvas.LeftProperty, newLeft); double newTop = e.GetPosition(canvas).Y - firstYPos - canvas.Margin.Top; // newTop inside canvas bottom-border? if (newTop > canvas.Margin.Top + canvas.ActualHeight - img.ActualHeight) newTop = canvas.Margin.Top + canvas.ActualHeight - img.ActualHeight; // newTop inside canvas top-border? else if (newTop < canvas.Margin.Top) newTop = canvas.Margin.Top; img.SetValue(Canvas.TopProperty, newTop); } } 

此代码允许我将图像拖放到Canvas中,而无需离开Canvas本身。

现在我只需要做两件事:

  1. 修复一个小小的bug,当我将它们拖动到快速时,我的鼠标滑动了Image。 这种情况经常发生,即使我甚至没有快速移动拖动图像。 使用我在其他问题中提到的解决方案。
  2. 使其能够一次拖放多个图像,最好先选择多个图像,然后在停留在Canvas中的同时拖放整个图像。

将为此提出一个新问题。

我做了一个项目,使用了一大块代码,并在canvas上拖放,查看它,看看是否有任何差异,没有真正的时间来检查

 private void pinCanvas_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e) { // Point pt = e.GetPosition(pinCanvas); // Curosor.Text = String.Format("You are at ({0}in, {1}in) in window coordinates", (pt.X / (96 / 72)) * 1/72, (pt.Y / (96 / 72)) * 1/72); } bool captured = false; double x_shape, x_canvas, y_shape, y_canvas; UIElement source = null; string elementName; double elementHeight, elementWidth; private void pinCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { setCanvasSize(); source = (UIElement)sender; elementName = ((Label)source).Name; switch (elementName) { case "pinTextBox" : elementHeight = pinActualHeight; elementWidth = pinActualWidth; break; case "serialTextBox" : elementHeight = serialActualHeight; elementWidth = serialActualWidth; break; case "batchTextBox" : elementHeight = batchActualHeight; elementWidth = batchActualWidth; break; } Mouse.Capture(source); captured = true; x_shape = Canvas.GetLeft(source); x_canvas = e.GetPosition(Maincanvas).X; y_shape = Canvas.GetTop(source); y_canvas = e.GetPosition(Maincanvas).Y; } private void pinCanvas_MouseMove(object sender, MouseEventArgs e) { if (captured) { double x = e.GetPosition(Maincanvas).X; double y = e.GetPosition(Maincanvas).Y; var xCond = Math.Round(appActivities.DIP2Inch(x_shape), 4).ToString(); var yCond = Math.Round(appActivities.DIP2Inch(y_shape), 4).ToString(); var name = ((Label)source).Name; x_shape += x - x_canvas; // if ((x_shape < Maincanvas.ActualWidth - elementWidth) && x_shape > 0) // { Canvas.SetLeft(source, x_shape); switch (name) { case "pinTextBox" : pinOffsetLeft.Text = xCond; break; case "serialTextBox" : serialOffsetLeft.Text = xCond; break; case "batchTextBox" : batchOffsetLeft.Text = xCond; break; } // } x_canvas = x; y_shape += y - y_canvas; // if (y_shape < Maincanvas.ActualHeight - elementHeight && y_shape > 0) // { Canvas.SetTop(source, y_shape); switch (name) { case "pinTextBox": pinOffsetTop.Text = yCond; break; case "serialTextBox": serialOffsetTop.Text = yCond; break; case "batchTextBox": batchOffsetTop.Text = yCond; break; } // } y_canvas = y; } } private void pinCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Mouse.Capture(null); captured = false; // MessageBox.Show((Canvas.GetTop(source)).ToString()); /* if (Canvas.GetTop(source) < 0) { Canvas.SetTop(source, 0); } if (Canvas.GetLeft(source) < 0) { Canvas.SetLeft(source, 0); } if (Canvas.GetLeft(source) > Maincanvas.ActualWidth - elementWidth) { // MessageBox.Show("Left Too Much " + (Canvas.GetLeft(source) * 1/96).ToString()); Canvas.SetLeft(source, Maincanvas.ActualWidth - elementWidth); } if (Canvas.GetTop(source) > Maincanvas.ActualHeight - elementHeight) { Canvas.SetTop(source, Maincanvas.ActualHeight - elementHeight); } */ oneElemntTorched = true; //MessageBox.Show(this.pinTextBox.ActualHeight.ToString() + ", " + this.pinTextBox.ActualWidth.ToString()); }