拖放:如何识别目标项条目
本文关键字:目标 识别 何识别 拖放 | 更新日期: 2023-09-27 18:06:30
我成功实现了两个DataGrids
之间的拖放,即目标DataGrid
知道源DataGrid
的哪些条目被选中,并可以使用它们进行进一步处理。
现在我想确定目标DataGrid
的入口,鼠标已经放置在那里。这是可能的吗?如果是,我该如何实现?
低于我的目标DataGrid
代码:
void TargetList_Drop(object sender, DragEventArgs e)
{
var mySourceRecords =
e.Data.GetData(typeof(List<MySourceRecord>))
as List<MySourceRecord>;
// Process selected vehicle variants
... mySourceRecords should be processed here with the target DataGrid record ...
}
您可以使用VisualTreeHelper.HitTest
执行命中测试
Point targetPoint = e.GetPosition(DataGrid1);
HitTestResult result = VisualTreeHelper.HitTest(DataGrid1, targetPoint);
DependencyObject dropTarget = result.VisualHit;
您可以使用InputHitTest
在datagrid上执行命中测试,以确定掉落的位置
Point targetPoint = e.GetPosition(DataGrid1);
IInputElement dropTarget = DataGrid1.InputHitTest(targetPoint);
在这些方法之后的dropTarget将是放置的位置。现在您可以通过几个方法来识别目标。
查看您的代码,似乎目标应该是发送方,这取决于您如何设置拖放。即:
void TargetList_Drop(object sender, DragEventArgs e)
{
var target = (FrameworkElement) sender;
}
但是,您可能订阅了数据网格上的drop,而不是它的可视化子元素,因此上述内容可能不适合您。
下面附加的行为可能有助于解决您的问题。我已经用了很多年了。您只需在可拖放的元素上设置IsDragSource,在可接受拖放的元素上设置IsDropTarget。我通常使用MVVM,所以我添加了一个DropCommand,以便它是视图模型来处理drop。
public static class DragAndDropManager
{
#region IsDragSource Attached Property
public static readonly DependencyProperty IsDragSourceProperty
= DependencyProperty.RegisterAttached("IsDragSource",typeof(bool),typeof(DragAndDropManager),new PropertyMetadata(IsDragSourceChanged));
public static void SetIsDragSource(DependencyObject d, bool value)
{
d.SetValue(IsDragSourceProperty, true);
}
public static bool GetIsDragSource(DependencyObject d)
{
return (bool)d.GetValue(IsDragSourceProperty);
}
private static void IsDragSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as FrameworkElement;
if (element == null)
return;
element.PreviewMouseMove += OnPreviewMouseMove;
}
private static void OnPreviewMouseMove(object sender, MouseEventArgs args)
{
var element = (FrameworkElement)sender;
var dragSource = args.OriginalSource as FrameworkElement;
if (args.LeftButton != MouseButtonState.Pressed
|| dragSource == null
|| dragSource.DataContext == null)
return;
var dragData = new DataObject(dragSource.DataContext);
DragDrop.DoDragDrop(element, dragData, DragDropEffects.Move);
}
#endregion
#region IsDropTarget Attached Property
public static readonly DependencyProperty IsDropTargetProperty
= DependencyProperty.RegisterAttached("IsDropTarget",typeof(bool),typeof(DragAndDropManager),new PropertyMetadata(IsDropTargetChanged));
public static void SetIsDropTarget(DependencyObject d, bool value)
{
d.SetValue(IsDropTargetProperty, true);
}
public static bool GetIsDropTarget(DependencyObject d)
{
return (bool)d.GetValue(IsDropTargetProperty);
}
private static void IsDropTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as FrameworkElement;
if (element == null)
return;
element.AllowDrop = true;
element.DragOver += OnDragOver;
element.Drop += OnDrop;
}
private static void OnDragOver(object sender, DragEventArgs e)
{
if (e.Data == null || e.Handled)
{
e.Effects = DragDropEffects.None;
return;
}
var element = (FrameworkElement)sender;
var command = GetDropCommand(element);
if (command == null)
return;
var dataFormats = e.Data.GetFormats();
if (dataFormats==null)
return;
var dragAndDropInfo = new DragAndDropInfo(element.DataContext,
e.Data.GetData(dataFormats.FirstOrDefault()));
var canDrop = dragAndDropInfo.DroppedItem != dragAndDropInfo.SourceItem
&& command.CanExecute(dragAndDropInfo);
e.Handled = true;
e.Effects = canDrop
? e.Effects = DragDropEffects.All
: DragDropEffects.None;
}
private static void OnDrop(object sender, DragEventArgs e)
{
if (e.Data == null || e.Handled)
return;
var element = (FrameworkElement)sender;
var command = GetDropCommand(element);
if (command == null)
return;
var dataFormats = e.Data.GetFormats();
if (dataFormats == null)
return;
var dragAndDropInfo = new DragAndDropInfo(element.DataContext,
e.Data.GetData(dataFormats.FirstOrDefault()));
var canDrop = dragAndDropInfo.DroppedItem != dragAndDropInfo.SourceItem
&& command.CanExecute(dragAndDropInfo);
if (canDrop)
{
command.Execute(dragAndDropInfo);
}
e.Handled = true;
}
#endregion
#region DropCommand Attached Property
public static readonly DependencyProperty DropCommandProperty
= DependencyProperty.RegisterAttached("DropCommand",typeof(ICommand),typeof(DragAndDropManager),new PropertyMetadata(DropCommandProperty));
public static void SetDropCommand(DependencyObject d, ICommand value)
{
d.SetValue(DropCommandProperty, value);
}
public static ICommand GetDropCommand(DependencyObject d)
{
return (ICommand)d.GetValue(DropCommandProperty);
}
#endregion
}
public class DragAndDropInfo
{
public object SourceItem { get; private set; }
public object DroppedItem { get; private set; }
public DragAndDropInfo(object sourceItem, object droppedItem)
{
SourceItem = sourceItem;
DroppedItem = droppedItem;
}
}
}
下面是TreeView示例的XAML示例。在你的例子中,你可以在行展示器上做类似的事情,等等<TreeView
Behaviors:DragAndDropManager.IsDropTarget="true"
Behaviors:DragAndDropManager.DropCommand="{Binding DropCommand}">
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Style.Setters>/>
<Setter Property="Behaviors:DragAndDropManager.IsDragSource" Value="true"/>
<Setter Property="Behaviors:DragAndDropManager.IsDropTarget" Value="true"/>
<Setter Property="Behaviors:DragAndDropManager.DropCommand" Value="{Binding DropCommand}"/>
</Style.Setters>
</Style>
</TreeView.Resources>
</TreeView>