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

可拖放的TreeView控件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.86/5 (18投票s)

2004年8月1日

4分钟阅读

viewsIcon

317477

downloadIcon

5542

一个内置拖放功能的树形视图。

Sample Image - DragDropTreeview.gif

引言

开发人员想要用树形视图实现的一种常见行为是拖放。出于某些原因,微软并没有让 .NET TreeView 控件完全轻松地实现这一点(即使在 2.0 beta 版中也没有改变)。虽然实现起来并不算太难,但最好有一个内置此功能的控件,而不是每次想在树形视图中实现拖放时都复制代码片段。

拖放主要围绕 4 个事件:OnDragDropOnDragEnterOnDragLeaveOnDragOver,以及在 TreeView 控件中的 OnItemDrag。我将不再详细介绍这些事件的调用顺序或它们的作用,您可以查阅 MSDN 文档或使用 Google。总而言之,这些事件已在此 TreeViewDragDrop 控件中实现。

控件的特性

我为我存储代码示例的网站(www.sloppycode.net,无耻的宣传)的一个管理应用程序构建了这个控件。牢记“编程是 90% 的设计”这句古老的格言,我写下了以下我希望控件实现的功能:

  • 自动滚动
  • 鼠标悬停在节点上时高亮目标节点
  • 拖动时的自定义光标
  • 拖动时的自定义幽灵图标标签
  • 按 Escape 键取消拖动
  • 通过 DragStart 事件阻止某些节点被拖动
  • 拖动时的健全性检查(不允许父节点拖动到子节点,目标不能是源节点)

上述部分功能并未在 MSDN 中记录,但如果仔细搜索 Google 群组和网站,可能会找到。我现在将逐步介绍这些核心功能的实现。

自动滚动

这是通过 WinAPI SendMessage 调用实现的。OnDragOver 事件执行一个 SendMessage 调用(277 是常量值,我猜是 WM_SCROLL,但我没查证)。这会根据鼠标位置向上或向下滚动树形视图。

高亮目标节点

这个实现起来相当简单,您只需在 OnDragOver 事件中更改目标节点的背景色和前景色。默认颜色基于 Windows Explorer,背景色使用系统的“高亮”颜色,前景色使用“高亮文本”颜色。我已将这些设置为控件的属性,以便用户可以随意更改。

拖动时的自定义光标

这是使用 OnGiveFeedback 事件实现的。该事件传递一个 GiveFeedbackEventArgs 类,其中包含一个 UseDefaultCursors 属性。如果我们要实现自定义光标,可以将此属性设置为 false,并将其更改为我们想要的光标。我们还会检查是否正在进行拖动,如果不是,则将光标恢复原状。

自定义幽灵图标

这是控件中最漂亮的功能,但也可能是 bug 的最大来源。它复制了 Windows Explorer 的行为,显示正在拖动的节点,以“幽灵化”或淡化的形式,包括节点的标签和图标。我通过使用第二个表单来实现这一点,该表单被移动到鼠标所在的位置。通过控件中的属性,您可以更改显示的图像以及标签的字体。这是一个比上面提到的自定义光标更好的版本,尽管我感觉我走了一条弯路,可能有一个 Windows API 调用已经完成了这项工作——问题是我不知道是什么。如果有人知道,请告知。

按 Escape 键取消拖动

这是 Windows Explorer 树形视图的另一个标准行为,即您可以通过按 Escape 键来取消拖动。OnKeyUp 事件用于执行此操作,它会检查按下的键是否是 Escape 键,如果是,则取消拖动,并将任何被拖动的节点恢复到其原始状态。

阻止某些节点被拖动

我在控件中添加了一些自定义事件,以增加一些小的额外事件功能。其中最主要的是 DragStart 事件。在拖动开始时会触发此事件,允许您检查正在拖动的节点,并在必要时阻止拖放事件。例如,如果您在树形视图中有一个回收站,并且不希望用户随意拖动它,那么这个功能就很有用。

拖动的健全性检查

这是为了防止节点拖动到自身内部或拖动到自身而内置的。它使用 Path 属性以最快的方式进行检查。这意味着,如果您有两个相同的路径,那么它将不起作用;您可能需要构建一个派生类来解决这个问题,并通过遍历父节点并逐个检查的方式来解决。

差不多就是这样了。我重写了 WndProc 事件,它阻止了树形视图在每次更新时重绘背景,从而消除了闪烁。当您拖动一个节点时,它仍然会有一点闪烁,但这似乎是 .NET 框架控件的一个问题。我已经尝试了双缓冲,但没有成功,欢迎任何建议。

希望它对某些人有所帮助。

拖放树形视图控件 - CodeProject - 代码之家
© . All rights reserved.