65.9K
CodeProject 正在变化。 阅读更多。
Home

非常简单的 WPF 拖放示例, 无需 Win32 调用

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.23/5 (16投票s)

2008年3月3日

CPOL

2分钟阅读

viewsIcon

147850

downloadIcon

4496

无需 P/Invoke 的拖放示例

引言

我从 Josh Smith 的文章 在 WPF ListView 中拖放项目中学到了如何在 WPF 中实现拖放。Josh 的优秀文章和附带的代码描述了许多与拖放功能相关的 WPF 特性。但是,我觉得大多数时候人们可能只想使用一个普通的、原始的拖放功能,而不需要大多数这些特性。对于这些人来说,这篇文章和相关的代码可能更有用。

除此之外,Josh 使用了 Dan Crevier 开发的 MouseUtilities 类,该类调用了一些 Win32 函数。我通过使用事件的 GetPosition 方法解决了这个问题。因此,应该可以在 Web 浏览器应用程序 (XBAP) 中使用这里提供的功能,没有任何问题。

后续说明 - 08 年 3 月 16 日添加:实际上,这是真的,在部分信任下,无法使用 DragDrop.DoDragDrop() 函数运行 XBAP 应用程序。要查看 XBAP 的拖放实现示例,请查看 为基于浏览器的 WPF 应用程序 (XBAP) 实现拖放操作。此外,对于多选拖放,请参阅 WPF 中的多选拖放

Using the Code

要使用代码,只需下载它,使用 Visual Studio 2008 打开项目,编译并运行即可。

使用拖放重新排序列表中的项目。

简短代码说明

基本上有三个包含代码的文件

  1. Shape.cs
  2. Window1.xaml
  3. Window.xaml.cs

Shape.cs 包含用于用作 ListView 后面的项目的非常简单对象的定义。每个项目都有一个名称和边数作为属性。

Window1.xaml 包含 XAML,表示一个非常简单的 Window,其中包含 ListView 控件。ListViewItemsSource 属性设置为指向 Shape 对象集合。

Window1.xaml.cs 包含所有 C# 管道和实际进行拖放的函数

  • ListView1_PreviewMouseLeftButtonDown - 启动拖动操作
  • ListView1_Drop - 完成放置操作

使用 Event Argument GetPosition 函数确定当前鼠标位置

DragEventArgsMouseButtonEventArgs 类都具有以下函数

Point GetPosition(IInputElement)

此函数返回相对于 Visual 元素的当前鼠标位置(作为参数传递给该函数)。由于 DragEventArgsMouseButtonEventArgs 没有定义 GetPosition 函数的公共超类或接口,因此我编写了将 GetPosition 函数作为 委托 的代码,以便能够将其重用于这两个类。以下是返回列表中当前项目 index 的功能

int GetCurrentIndex(GetPositionDelegate getPosition)
{
    int index = -1;
    for (int i = 0; i < this.ListView1.Items.Count; ++i)
    {
        ListViewItem item = GetListViewItem(i);
        if (this.IsMouseOverTarget(item, getPosition))
        {
            index = i;
            break;
        }
    }
    return index;
}

bool IsMouseOverTarget( Visual target, GetPositionDelegate getPosition)
{
    Rect bounds = VisualTreeHelper.GetDescendantBounds( target );
    Point mousePos = getPosition((IInputElement) target);
    return bounds.Contains( mousePos );
}

GetPositionDelegate 定义为

delegate Point GetPositionDelegate(IInputElement element);

以下是函数 GetCurrentIndex 的调用方式:来自 ListView1_Drop 函数 - 负责放置操作(此函数使用 DragEventArgs

void ListView1_Drop(object sender, DragEventArgs e)
{
     ...
     int index = this.GetCurrentIndex(e.GetPosition);
     ...
}

来自 ListView1_PreviewMouseLeftButtonDown 函数 - 负责启动拖动操作(此函数使用 MouseButtonEventArgs

void ListView1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    ...
    oldIndex = this.GetCurrentIndex(e.GetPosition);
    ...
}

历史

  • 2008 年 3 月 3 日:初始帖子
  • 2008 年 3 月 16 日:添加了对其他拖放文章的引用
© . All rights reserved.