WPF拖拽交互全攻略及实现自定义拖拽控件及数据交换技巧解析

1. 基本概念

拖拽(Drag and Drop)是一种常见的用户交互方式、数据传输方法。允许用户通过拖动鼠标来移动或复制数据。
在WPF 中的拖拽操作主要涉及以下几个概念:

  • 拖动源(Drag Source):用户开始拖动的控件。
  • 拖动目标(Drop Target):用户释放拖动的控件。
  • 数据对象(Data Object):封装拖动过程中传递的数据。
  1. 可以通过拖放操作的对象的类型和数量是完全任意的。
    例如,文件、文件夹和内容选择是通过拖放操作操作的一些更常见的对象。
  2. 拖拽源和放置目标可以是同一应用程序或不同应用程序中的UI元素。
  3. 拖放支持在单个应用程序内或不同应用程序之间操作对象。
  4. 还完全支持 WPF 应用程序和其他 Windows 应用程序之间的拖放。
  5. 在 WPF 中,任何 UIElement 或 ContentElement 都可以参与拖放。
    UIElement 和 ContentElement 类包含 DragDrop 附加事件的别名,以便当 UIElement 或 ContentElement 作为基本元素继承时,这些事件会出现在类成员列表中。

2 . 实现拖拽功能

概述

需要要实现基本的拖放,完成以下任务:
  1. 确定将成为拖动源的元素。拖动源可以是 UIElement 或 ContentElement。
  2. 在将启动拖放操作的拖动源上创建一个事件处理程序。该事件通常是 MouseMove 事件。
  3. 在拖动源事件处理程序中,调用 DoDragDrop 方法来启动拖放操作。在 DoDragDrop 调用中,指定拖动源、要传输的数据以及允许的效果。
  4. 确定将成为放置目标的元素。放置目标可以是 UIElement 或 ContentElement。
  5. 在放置目标上,将AllowDrop 属性设置为 。
  6. 在放置目标中,创建一个 Drop 事件处理程序来处理放置的数据。
  7. 在 Drop 事件处理程序中,使用 GetDataPresent 和 GetData 方法从 DragEventArgs 中提取数据。
  8. 在 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,表示CopyMoveScroll效果的组合。

  • GiveFeedback

  1. GiveFeedback具有默认处理程序,通常可这些事件,除非有特定需要更改它们的默认行为。

  2. 拖动拖动源时,会连续引发 GiveFeedback 事件。

  3. 此事件的默认处理程序检查拖动源是否位于有效的放置目标上方。

    如果是,它会检查放置目标允许的效果。然后,它向最终用户提供有关允许的放置效果的反馈。

    例如:将鼠标光标更改为不可放置、复制或移动光标来完成的。

  4. 如果处理此事件,请务必将其标记为已处理,以便默认处理程序不会覆盖您的处理程序。

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 设置放置目标,处理拖拽数据
  1. 指定它是有效的放置目标
    AllowDrop 属性设置为true
  2. 当拖动源拖过目标时响应拖动源
拖拽输入DragEnter事件

当数据被拖入放置目标的边界时;
不要在 DragEnter 事件中设置 DragEventArgs.Effects 属性,因为它会在 DragOver 事件中被覆盖。
示例<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值