目录
1. 基本概念
拖拽(Drag and Drop)是一种常见的用户交互方式、数据传输方法。允许用户通过拖动鼠标来移动或复制数据。
在WPF 中的拖拽操作主要涉及以下几个概念:
- 拖动源(Drag Source):用户开始拖动的控件。
- 拖动目标(Drop Target):用户释放拖动的控件。
- 数据对象(Data Object):封装拖动过程中传递的数据。
- 可以通过拖放操作的对象的类型和数量是完全任意的。
例如,文件、文件夹和内容选择是通过拖放操作操作的一些更常见的对象。 - 拖拽源和放置目标可以是同一应用程序或不同应用程序中的UI元素。
- 拖放支持在单个应用程序内或不同应用程序之间操作对象。
- 还完全支持 WPF 应用程序和其他 Windows 应用程序之间的拖放。
- 在 WPF 中,任何 UIElement 或 ContentElement 都可以参与拖放。
UIElement 和 ContentElement 类包含 DragDrop 附加事件的别名,以便当 UIElement 或 ContentElement 作为基本元素继承时,这些事件会出现在类成员列表中。
2 . 实现拖拽功能
概述
需要要实现基本的拖放,完成以下任务:
- 确定将成为拖动源的元素。拖动源可以是 UIElement 或 ContentElement。
- 在将启动拖放操作的拖动源上创建一个事件处理程序。该事件通常是 MouseMove 事件。
- 在拖动源事件处理程序中,调用 DoDragDrop 方法来启动拖放操作。在 DoDragDrop 调用中,指定拖动源、要传输的数据以及允许的效果。
- 确定将成为放置目标的元素。放置目标可以是 UIElement 或 ContentElement。
- 在放置目标上,将AllowDrop 属性设置为 。
- 在放置目标中,创建一个 Drop 事件处理程序来处理放置的数据。
- 在 Drop 事件处理程序中,使用 GetDataPresent 和 GetData 方法从 DragEventArgs 中提取数据。
- 在 Drop 事件处理程序中,使用数据执行所需的拖放操作。
其他操作
要在拖动期间执行其他操作,请处理放置目标上的 DragEnter、DragOver 和 DragLeave 事件。
要更改鼠标指针的外观,请处理拖动源上的 GiveFeedback 事件。
要更改取消拖放操作的方式,请处理拖动源上的 QueryContinueDrag 事件。
示例
本节介绍如何实现椭圆元素的拖放。椭圆既是拖动源又是放置目标。传输的数据是椭圆的 Fill 属性的字符串表示形式。
<Ellipse Height="50" Width="50" Fill="Green"
MouseMove="ellipse_MouseMove"
GiveFeedback="ellipse_GiveFeedback"
AllowDrop="True"
DragEnter="ellipse_DragEnter"
DragLeave="ellipse_DragLeave"
DragOver="ellipse_DragOver"
Drop="ellipse_Drop" />
3.1 设置拖拽源,拖拽开始
示例
private void ellipse_MouseMove(object sender, MouseEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
if (ellipse != null && e.LeftButton == MouseButtonState.Pressed)
{
DragDrop.DoDragDrop(ellipse,
ellipse.Fill.ToString(),
DragDropEffects.Copy);
}
}
在 MouseMove 事件处理程序内部,调用 DoDragDrop 方法来启动拖放操作。 DoDragDrop 方法采用三个参数:
dragSource
– 对作为传输数据源的依赖对象的引用;这通常是 MouseMove 事件的来源。data
- - 包含传输数据的对象,包装在 DataObject 中。
任何可序列化的对象都可以在参数中传递。如果数据尚未包装在 DataObject 中,它将自动包装在新的 DataObject 中。要传递多个数据项,您必须自己创建 DataObject,并将其传递给 DoDragDrop 方法。
// 创建一个新的 DataObject
DataObject dataObject = new DataObject();
// 添加多个数据项
dataObject.SetData("Text", "这是一个文本数据");
dataObject.SetData("Number", 12345);
dataObject.SetData("Date", DateTime.Now);
// 启动拖放操作
DragDropEffects effects = DragDrop.DoDragDrop((DependencyObject)sender, dataObject, DragDropEffects.Copy);
allowedEffects
- DragDropEffects 枚举值之一,指定允许的拖放操作效果。
3.2 设置拖拽效果
向用户提供有关允许的操作(移动、复制、无)的反馈,并且可以基于附加的用户输入(例如在拖动期间按 ESC 键)取消拖放操作。可以选择处理拖动源上的 GiveFeedback 和 QueryContinueDrag 事件。
DragDropEffects
WPF 定义了一个 DragDropEffects
枚举用于指定拖放操作的效果。它支持按位组合其成员值,以便在拖放操作中表示不同的效果。
DragDropEffects
枚举包含以下成员:
-
None: 值为0,表示放置目标不接受数据。
-
Copy: 值为1,将拖动源中的数据复制到放置目标。
-
Move: 值为2,将拖动源中的数据移动到放置目标。
-
Link: 值为4,将拖动源中的数据链接到放置目标。
-
Scroll: 值为-2147483648,拖动时可以滚动目标,以定位在目标中当前不可见的某个放置位置。
-
All: 值为-2147483645,表示
Copy
、Move
和Scroll
效果的组合。 -
GiveFeedback
-
GiveFeedback具有默认处理程序,通常可这些事件,除非有特定需要更改它们的默认行为。
-
拖动拖动源时,会连续引发 GiveFeedback 事件。
-
此事件的默认处理程序检查拖动源是否位于有效的放置目标上方。
如果是,它会检查放置目标允许的效果。然后,它向最终用户提供有关允许的放置效果的反馈。
例如:将鼠标光标更改为不可放置、复制或移动光标来完成的。
-
如果处理此事件,请务必将其标记为已处理,以便默认处理程序不会覆盖您的处理程序。
private void Element_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (e.Effects == DragDropEffects.Copy)
{
// 更改鼠标光标为复制光标
Mouse.SetCursor(Cursors.Cross);
}
else
{
// 更改鼠标光标为不可放置光标
Mouse.SetCursor(Cursors.No);
}
// 标记事件为已处理
e.Handled = true;
}
- QueryContinueDrag
拖动拖动源时会连续引发 QueryContinueDrag 事件。
可以处理此事件,以根据 ESC、SHIFT、CTRL 和 ALT 键的状态以及鼠标按钮的状态确定结束拖放操作的操作。
如果按下 ESC 键,此事件的默认处理程序将取消拖放操作;
如果释放鼠标按钮,则删除数据。
这些事件在拖放操作期间不断引发。因此,您应该避免在事件处理程序中执行资源密集型任务。 例如,使用缓存的游标而不是每次引发 GiveFeedback 事件时创建新游标。
private void Element_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
// 如果按下 ESC 键,则取消拖放操作
if (e.EscapePressed)
{
e.Action = DragAction.Cancel;
}
// 如果释放鼠标按钮,则删除数据
else if (e.KeyStates == DragDropKeyStates.None)
{
e.Action = DragAction.Drop;
else
{
e.Action = DragAction.Continue;
}
Mouse.SetCursor(Cursors.Arrow);
}
3.3 设置放置目标,处理拖拽数据
- 指定它是有效的放置目标
AllowDrop 属性设置为true
- 当拖动源拖过目标时响应拖动源
拖拽输入DragEnter事件
当数据被拖入放置目标的边界时;
不要在 DragEnter 事件中设置 DragEventArgs.Effects 属性,因为它会在 DragOver 事件中被覆盖。
示例<