如何使用 C# 在 WPF 中的 Canvas 内拖放图像
How To Drag and Drop Images inside Canvas in WPF using C#
我能够将图像作为子元素动态添加到 WPF Canvas 控件中,但无法将这些图像拖放到 canvas 中。请帮助我如何移动或 canvas window 中的 drag/drop 图像。
提前致谢。
以下是我目前所做的:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonDown="MouseLeftButtonDown"
PreviewMouseLeftButtonUp="MouseLeftButtonUp"
PreviewMouseMove="MouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
**Code**
OpenFileDialog op = new OpenFileDialog();
op.Title = "Select Multiple Pictures";
op.Multiselect = true;
op.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) |
*.jpg; *.jpeg; *.jpe; *.jfif; *.png";
foreach (string imageFile in op.FileNames)
{
Image img = new Image();
img.Source = new BitmapImage(new Uri(imageFile));
img.Height = 100;
img.Width = 100;
img.AllowDrop = true;
Canvas.SetTop(img, y); //Setting up images to the Top position
Canvas.SetLeft(img, x); //Setting up images to the left position
canvasImages.Children.Add(img);
}
private new void MouseLeftButtonDown(object sender,
MouseButtonEventArgs
e)
{
IsDragging = true;
draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(draggedItem);
}
private new void MouseMove(object sender,
System.Windows.Input.MouseEventArgs e)
{
if (!IsDragging)
return;
Point canvasRelativePosition = e.GetPosition(canvasImages);
Canvas.SetTop(draggedItem, canvasRelativePosition.Y -
itemRelativePosition.Y);
Canvas.SetLeft(draggedItem, canvasRelativePosition.X -
itemRelativePosition.X);
}
private new void MouseLeftButtonUp(object sender, MouseButtonEventArgs
e)
{
if (!IsDragging)
return;
IsDragging = false;
}
@Mark,这是 XAML 代码和相应的 Class 供您阅读。基本上我允许通过 "OpenFileDialog()" 选择多个图像并将这些图像动态添加到 Canvas 控件,如我之前的代码中所述,然后我无法在 [=25= 内部拖动这些图像] 控制。
下面是XAML代码
<Window x:Class="PicturesMovement.CanvasControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connectlite Clients"
Height="394" Width="445"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<Grid Margin="0,0,2,0" Background="{DynamicResource {x:Static
SystemColors.MenuBarBrushKey}}">
<Button x:Name="Select" Content="Select" HorizontalAlignment="Left"
Height="22" Margin="329,328,0,0" VerticalAlignment="Top" Width="42"
Click="SelectImages"/>
<Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Left"
Margin="374,328,0,0" VerticalAlignment="Top" Width="49"
Click="closeBox"/>
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0"
Width="430" HorizontalAlignment="Left" VerticalAlignment="Top"
AllowDrop="True" PreviewMouseDown="PreviewMouseDown"
PreviewMouseUp="PreviewMouseUp"
PreviewMouseMove="PreviewMouseMove" MaxWidth="430"
MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
</Window>
下面是触发这些鼠标事件的相应 Class
public partial class CanvasControl : System.Windows.Window,
System.Windows.Markup.IComponentConnector {
this.canvasImages.PreviewMouseDown += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseDown);
this.canvasImages.PreviewMouseUp += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseUp);
this.canvasImages.PreviewMouseMove += new
System.Windows.Input.MouseEventHandler
(this.PreviewMouseMove);
}
任何建议将不胜感激...谢谢
好的,这里有一些错误...
1) 您的鼠标按下处理程序必须在图像上,而不是 canvas,否则您的代码无法知道正在拖动哪个项目。
2) 单击图像后,处理程序应为 canvas 捕获鼠标,以便您获得所有鼠标移动消息。
3) 然后需要相应地处理 Canvas MouseMove 和 MouseUp 处理程序。
4) Canvas需要有背景。如果你不给它一个背景,那么它对命中测试是有效透明的,你不会得到它的鼠标消息。如果您不希望它有可见的背景,请将其设置为 Transparent
.
因此您的 Canvas 标签需要如下所示:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonUp="CanvasImages_PreviewMouseLeftButtonUp"
PreviewMouseMove="CanvasImages_PreviewMouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
Background="Transparent" />
并且您创建的每个图像都需要为其 MouseDown 事件设置一个处理程序:
img.MouseLeftButtonDown += Img_MouseLeftButtonDown;
那么只需像这样实现您的处理程序即可:
private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(this.draggedItem);
e.Handled = true;
}
private void CanvasImages_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (this.draggedItem == null)
return;
var newPos = e.GetPosition(canvasImages) - itemRelativePosition;
Canvas.SetTop(this.draggedItem, newPos.Y);
Canvas.SetLeft(this.draggedItem, newPos.X);
canvasImages.CaptureMouse();
e.Handled = true;
}
private void CanvasImages_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (this.draggedItem != null)
{
this.draggedItem = null;
canvasImages.ReleaseMouseCapture();
e.Handled = true;
}
}
我能够将图像作为子元素动态添加到 WPF Canvas 控件中,但无法将这些图像拖放到 canvas 中。请帮助我如何移动或 canvas window 中的 drag/drop 图像。
提前致谢。
以下是我目前所做的:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonDown="MouseLeftButtonDown"
PreviewMouseLeftButtonUp="MouseLeftButtonUp"
PreviewMouseMove="MouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
**Code**
OpenFileDialog op = new OpenFileDialog();
op.Title = "Select Multiple Pictures";
op.Multiselect = true;
op.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) |
*.jpg; *.jpeg; *.jpe; *.jfif; *.png";
foreach (string imageFile in op.FileNames)
{
Image img = new Image();
img.Source = new BitmapImage(new Uri(imageFile));
img.Height = 100;
img.Width = 100;
img.AllowDrop = true;
Canvas.SetTop(img, y); //Setting up images to the Top position
Canvas.SetLeft(img, x); //Setting up images to the left position
canvasImages.Children.Add(img);
}
private new void MouseLeftButtonDown(object sender,
MouseButtonEventArgs
e)
{
IsDragging = true;
draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(draggedItem);
}
private new void MouseMove(object sender,
System.Windows.Input.MouseEventArgs e)
{
if (!IsDragging)
return;
Point canvasRelativePosition = e.GetPosition(canvasImages);
Canvas.SetTop(draggedItem, canvasRelativePosition.Y -
itemRelativePosition.Y);
Canvas.SetLeft(draggedItem, canvasRelativePosition.X -
itemRelativePosition.X);
}
private new void MouseLeftButtonUp(object sender, MouseButtonEventArgs
e)
{
if (!IsDragging)
return;
IsDragging = false;
}
@Mark,这是 XAML 代码和相应的 Class 供您阅读。基本上我允许通过 "OpenFileDialog()" 选择多个图像并将这些图像动态添加到 Canvas 控件,如我之前的代码中所述,然后我无法在 [=25= 内部拖动这些图像] 控制。
下面是XAML代码
<Window x:Class="PicturesMovement.CanvasControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connectlite Clients"
Height="394" Width="445"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<Grid Margin="0,0,2,0" Background="{DynamicResource {x:Static
SystemColors.MenuBarBrushKey}}">
<Button x:Name="Select" Content="Select" HorizontalAlignment="Left"
Height="22" Margin="329,328,0,0" VerticalAlignment="Top" Width="42"
Click="SelectImages"/>
<Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Left"
Margin="374,328,0,0" VerticalAlignment="Top" Width="49"
Click="closeBox"/>
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0"
Width="430" HorizontalAlignment="Left" VerticalAlignment="Top"
AllowDrop="True" PreviewMouseDown="PreviewMouseDown"
PreviewMouseUp="PreviewMouseUp"
PreviewMouseMove="PreviewMouseMove" MaxWidth="430"
MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
</Window>
下面是触发这些鼠标事件的相应 Class
public partial class CanvasControl : System.Windows.Window,
System.Windows.Markup.IComponentConnector {
this.canvasImages.PreviewMouseDown += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseDown);
this.canvasImages.PreviewMouseUp += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseUp);
this.canvasImages.PreviewMouseMove += new
System.Windows.Input.MouseEventHandler
(this.PreviewMouseMove);
}
任何建议将不胜感激...谢谢
好的,这里有一些错误...
1) 您的鼠标按下处理程序必须在图像上,而不是 canvas,否则您的代码无法知道正在拖动哪个项目。
2) 单击图像后,处理程序应为 canvas 捕获鼠标,以便您获得所有鼠标移动消息。
3) 然后需要相应地处理 Canvas MouseMove 和 MouseUp 处理程序。
4) Canvas需要有背景。如果你不给它一个背景,那么它对命中测试是有效透明的,你不会得到它的鼠标消息。如果您不希望它有可见的背景,请将其设置为 Transparent
.
因此您的 Canvas 标签需要如下所示:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonUp="CanvasImages_PreviewMouseLeftButtonUp"
PreviewMouseMove="CanvasImages_PreviewMouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
Background="Transparent" />
并且您创建的每个图像都需要为其 MouseDown 事件设置一个处理程序:
img.MouseLeftButtonDown += Img_MouseLeftButtonDown;
那么只需像这样实现您的处理程序即可:
private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(this.draggedItem);
e.Handled = true;
}
private void CanvasImages_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (this.draggedItem == null)
return;
var newPos = e.GetPosition(canvasImages) - itemRelativePosition;
Canvas.SetTop(this.draggedItem, newPos.Y);
Canvas.SetLeft(this.draggedItem, newPos.X);
canvasImages.CaptureMouse();
e.Handled = true;
}
private void CanvasImages_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (this.draggedItem != null)
{
this.draggedItem = null;
canvasImages.ReleaseMouseCapture();
e.Handled = true;
}
}