【发布时间】:2016-10-19 04:05:19
【问题描述】:
我有一个 ListBox 和一个 Canvas。我想将 ListBoxItem 拖到画布上,正好放在鼠标所在的位置。这是我的 xaml。问题是无论鼠标位置如何,这些项目都被放置在其他项目之上。如何根据画布上的鼠标指针将拖动的项目放置在确切的位置。请帮忙。
<DockPanel LastChildFill="True" >
<ListBox DockPanel.Dock="Left" Name="lstLabels">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBoxItem_PreviewMouseLeftButtonDown"/>
<EventSetter Event="PreviewMouseMove" Handler="ListBoxItem_PreviewMouseMove"/>
</Style>
</ListBox.Resources>
<ListBoxItem>A</ListBoxItem>
<ListBoxItem>B</ListBoxItem>
<ListBoxItem>C</ListBoxItem>
<ListBoxItem>D</ListBoxItem>
<ListBoxItem>E</ListBoxItem>
<ListBoxItem>F</ListBoxItem>
<ListBoxItem>G</ListBoxItem>
<ListBoxItem>H</ListBoxItem>
</ListBox>
<Canvas AllowDrop="True" Background="Azure"
DragEnter="cvsSurface_DragEnter" Drop="cvsSurface_Drop"
Name="cvsSurface" >
</Canvas>
</DockPanel>
这是我完整的cs代码
private ListBoxItem draggedItem;
private Point startDragPoint;
private void cvsSurface_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Text))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
}
private void cvsSurface_Drop(object sender, DragEventArgs e)
{
Label newLabel = new Label();
newLabel.Content = e.Data.GetData(DataFormats.Text);
cvsSurface.Children.Add(newLabel);
Canvas.SetLeft(newLabel, 100);
Canvas.SetTop(newLabel, 200);
draggedItem = null;
lstLabels.SelectedItem = null;
}
private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
draggedItem = sender as ListBoxItem;
startDragPoint = e.GetPosition(null);
}
private void ListBoxItem_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point position = e.GetPosition(null);
if (draggedItem != null)
{
DragDrop.DoDragDrop(draggedItem, draggedItem.Content, DragDropEffects.Copy);
}
}
【问题讨论】:
-
您的 'dropped' 标签布局位置被硬编码为 {100, 200},您为什么希望它们不会一个接一个地出现?使用
DragEventArgs'GetPosition()方法获取Cavas内的相对鼠标点。 -
对不起,我的坏。正如你所说,我做了 var canvas = sender as Canvas; var positionX = e.GetPosition(canvas).X; var positionY = e.GetPosition(canvas).Y;并作为参数而不是 100 和 200 传递,它工作正常。如果它对某人有帮助,我将保持原样。
-
一个问题安德鲁。现在让我们说列表框项目是椭圆或矩形。现在在 cvsSurface_Drop 事件中,我说类似 StackPanel p=new StackPanel(); p.Children.Add(e.Data.GetData(DataFormats.Text));现在我该说什么而不是 Text 来添加形状?
-
DragEventArgs.Data 对象有许多方法可以查询哪些格式可用。但是如果你只使用矩形和椭圆,你可以使用像 e.Data.GetData(typeof(Shape)) 这样的东西。尽管如此,我认为您仍需要一些额外的逻辑来重新创建形状,因为您不能只将 UIElement 添加到可视化树中两次。
-
谢谢 Andrew 我想我需要从可视树中检索形状。当我尝试 UIElement sp = e.Data.GetData(typeof(Shape)) as UIElement; sp 始终为空。所以我需要从visualtree中获取基于id的形状吗?