日期:2008-07-16  浏览次数:20476 次

执行托放操作

定义了treeview 显示得内容以后,现在你应该准备处理如何四处移动元素了,大多数得开发人员在处理拖放操作时得通用观念都是很相似得,无论使用visual c++ visual basic 或者任何一种.net 语言,所以我一直用下面的四个方法处理这个操作:


MouseDown-----用户选择得内容

DragEnter---用户开始拖动选中得项目

DragOver ---用户拖动选中得项目经过另一个项目

DragDrop---用户在某个地方放下选择得项目

执行这些方法适当得给用户针对可以和不可以处理的得操作分别给予视觉反馈,同时告诉用户他们是怎样被执行的,并且不用管给定的上下文的细节操作,所以就有三个直接的问题需要被考虑:

1. 你如何使treeview 控件中的一个节点和底层XML文档中的节点进行匹配

2. 为了物理节点能够跟随图形进行转换,用户如何操作XML文档

3. 你如何有效地执行大的XML文档。如果这样的转变要不得不加强时,你不想把没有必要的东西绑定到用户界面

清单1

A TreeNode's position maps to an XML node using an XPath query.

Private Sub XMLTreeView_MouseDown(ByVal sender As Object, ByVal e As _
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
' First check whether we've clicked on a node in the tree view; if not,
' just return
Dim pt As New Point(e.X, e.Y)
drag_node = Me.GetNodeAt(pt)

If drag_node Is Nothing Then Return

' Highlight the node and build an xpath query so that we can remove it later
xpath_remove_query = buildXPathQuery(drag_node)
Me.SelectedNode = drag_node

' Decide whether we're going to perform an intra-folder rearrangement (right
' mouse button) or a genuine drag-and-drop (left mouse button);
' we do this in the MouseDown rather than DragEnter method, since by the time
' DragEnter fires, the mouse may well have been dragged to a different node
If e.Button = System.Windows.Forms.MouseButtons.Right Then
right_mouse_drag = True
Else
right_mouse_drag = False
End If
End Sub

Private Function buildXPathQuery(ByVal node As System.Windows.Forms.TreeNode) As String
Dim query As String = ""

Do
query = "*[" & xpath_filter & "][" & (node.Index + 1) & "]/" & query
node = node.Parent
Loop While Not (node Is Nothing)

Return query.Substring(0, query.Length - 1)
End Function




显示了MouseDown 句柄 和它调用的帮助方法buildXPathQuery,首先代码检查一个被选中的节点,接着通过使用事先定义好的筛选, 存储TreeNode (drag_node) 和使它关联到XML文档根节点的Xpath 查询(xpath_remove_query)。 例如下面的查询确定了树的根节点的第二个孩子有五个孩子文件夹,一个文件夹可以用查询"attribute::id." 唯一确定

*[attribute::id][2]/*[attribute::id][5]
当用户拖动一个节点到另外一个位置时,代码列表1提供了移动treenode 和treenode相关联的XMLNode的足够信息。你也许认为你能够得到相同的效果,而完全没有必要引用筛选,并且简单的指定像“托动文档根节点的第二个孩子到第一个孩子节点内部”这样的事情,但是这里不是你认为的那样,应该是筛选器强迫treeview 的节点层次和XML文档一一对应的,没有了它 ,这样的直接使用可能是不明智的,例如假设筛选器匹配下面的结构:

<contact>
<email />
<city />
<country />
</contact>
这样的约束意味着Xpath 筛选器将contacts.XML的层次作为一个简单的子元素列表看待

[0] <contacts>
[0] <contact="Alex">
[1] <contact="Rebekah">
[2] <contact="Justin">
然而,treeview 将相同的文档看作一个节点的层次列表

[0] <contacts>
[0] <contact="Alex">
[0] <email>
[1] <city>
[2] <country>
[1] <contact="Rebekah">
只要联系点从不和另一个联系点嵌套,你就能保持treeview 和 XML文档保持同步而没有必要求助于筛选器,例如 如果你想交换"Alex"和"Rebekah"联系点入口,你可以很容易的这么做:
指令: 移除 node[0], child[0];在node[0], child[0]之后重新插入它
treeview: 移除叫做"Alex"的"contact"节点,在叫做"Rebekah" 的"contact"节点之后从新插入它
XML文档:移除叫做"Alex"的"contact"节点,在叫做"Rebekah" 的"contact"节点之后从新插入
但是嵌套的contacts,相同的指令会引起TreeView表示和XML文档表示对不准。例如 假设你试图移动在下面treeview表示中嵌套的"Rebekah":