我对我将提供的“解决方案”并不完全满意。它们很可能与理想的实现相去甚远,但是...
我创建的XAML 代码试图轻松地复制,但也始终如一地复制您的对象,包括一组可拖动的Rectangles 在StackPanel 控件内,加上另一个StackPanel 控件可以在哪里被拖进去。
<Grid>
<Grid.Resources>
<Style TargetType="Rectangle">
<Setter Property="Width" Value="300"/>
<Setter Property="Height" Value="300"/>
<Setter Property="CanDrag" Value="True"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Name="StackPanelRectangles" Grid.Row="0" Orientation="Horizontal">
<Rectangle x:Name="RedRect" Fill="Red" DragStarting="Rectangle_DragStarting"/>
<Rectangle x:Name="GreenRect" Fill="Green" DragStarting="Rectangle_DragStarting"/>
<Rectangle x:Name="BlueRect" Fill="Blue" DragStarting="Rectangle_DragStarting"/>
</StackPanel>
<StackPanel Name="StackPanelDropArea" Background="Azure" AllowDrop="True"
DragOver="StackPanel_DragOver" Drop="StackPanel_Drop"
Grid.Row="2" Orientation="Horizontal"
HorizontalAlignment="Center">
<TextBlock>Drop anywhere in this area area</TextBlock>
</StackPanel>
</Grid>
第一种解决方案:
我将多个Rectangles 的每个DragStarting 事件路由到同一个EventHandler。在这个 EventHandler 中,我们可以访问被拖动的 UIElement,因此在您的 Page 类中使用 UIElement 类型的公开属性,您可以在需要删除它时简单地克隆必要的属性,就像这样:
UIElement dragItem;
private void Rectangle_DragStarting(UIElement sender, DragStartingEventArgs args)
{
dataPackage.RequestedOperation = DataPackageOperation.Copy;
dragItem = sender;
}
然后,当项目被删除时调用 EventHandler,我只需将它添加到我的 DropArea 中。
private void StackPanel_Drop(object sender, DragEventArgs e)
{
Rectangle newElement = new Rectangle();
newElement.Width = (dragItem as Rectangle).Width;
newElement.Height = (dragItem as Rectangle).Height;
newElement.Fill = (dragItem as Rectangle).Fill;
StackPanelDropArea.Children.Add(newElement);
}
您不能通过设置引用被拖动的对象来添加新控件,因为当您尝试将控件添加到不同的容器时,有一些属性(例如相应的 Parent)会引发异常。
第二个解决方案:
我非常专注于使用DataPackage 对象及其支持的默认格式之一,但我认为它们中的任何一个都不能真正保存对象的数据,例如我们的 UIElement。
但是每个DataPackage 实例都支持一组属性,对应一个字典。我们可以将 Dictionary 设置为在其中保存 UIElement,只要我们稍后指定一个键来引用同一个对象。
private void Rectangle_DragStarting(UIElement sender, DragStartingEventArgs args)
{
dataPackage.RequestedOperation = DataPackageOperation.Copy;
args.Data.Properties.Add("myRectangle", sender);
}
在drop Event Handler中,可以获取UIElement,如下:
private async void StackPanel_Drop(object sender, DragEventArgs e)
{
Rectangle element = e.DataView.Properties["myRectangle"] as Rectangle;
......
......
}
第三种解决方案:
此解决方案使用DataPackage 公开的方法SetText(String) 来保存被拖动的UIElement 的Name 属性的值。
private void Rectangle_DragStarting(UIElement sender, DragStartingEventArgs args)
{
dataPackage = new DataPackage();
dataPackage.RequestedOperation = DataPackageOperation.Copy;
Rectangle rectangle = sender as Rectangle;
dataPackage.SetText(rectangle.Name);
Clipboard.SetContent(dataPackage);
}
通过知道被拖动的UIElement 的Name 属性的值,通过使用VisualTreeHelper 类来查找它,如下所示:
private async void StackPanel_Drop(object sender, DragEventArgs e)
{
DataPackageView dataPackageView = Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text))
{
draggedObject = await dataPackageView.GetTextAsync();
}
// Dragged objects come from another one of our Parent's Children
DependencyObject parent = VisualTreeHelper.GetParent(StackPanelDropArea);
int count = VisualTreeHelper.GetChildrenCount(parent);
for(int i=0; i< count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if(child.GetType().Equals(typeof(StackPanel)))
{
StackPanel currentStackPanel = child as StackPanel;
if(currentStackPanel.Name == "StackPanelRectangles")
{
int numberOfRectangles = VisualTreeHelper.GetChildrenCount(currentStackPanel);
for(int j=0; j<numberOfRectangles; j++)
{
if(VisualTreeHelper.GetChild(currentStackPanel,j).GetType().Equals(typeof(Rectangle)))
{
Rectangle currentRectangle = VisualTreeHelper.GetChild(currentStackPanel, j) as Rectangle;
if (draggedObject != string.Empty && currentRectangle.Name.Equals(draggedObject))
{
Rectangle newRectangle = new Rectangle();
newRectangle.Width = currentRectangle.Width;
newRectangle.Height = currentRectangle.Height;
newRectangle.Fill = currentRectangle.Fill;
StackPanelDropArea.Children.Add(newRectangle);
}
}
}
}
}
} */
}
结果: