是在树景中上下移动节点的最准确方法。我在每个节点上都有一个上下文菜单,并且应使用其所有子节点移动选定的节点。 我使用c#.net 3.5winforms
您可以使用以下扩展名:
public static class Extensions
{
public static void MoveUp(this TreeNode node)
{
TreeNode parent = node.Parent;
TreeView view = node.TreeView;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index > 0)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index - 1, node);
}
}
else if (node.TreeView.Nodes.Contains(node)) //root node
{
int index = view.Nodes.IndexOf(node);
if (index > 0)
{
view.Nodes.RemoveAt(index);
view.Nodes.Insert(index - 1, node);
}
}
}
public static void MoveDown(this TreeNode node)
{
TreeNode parent = node.Parent;
TreeView view = node.TreeView;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index < parent.Nodes.Count -1)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index + 1, node);
}
}
else if (view != null && view.Nodes.Contains(node)) //root node
{
int index = view.Nodes.IndexOf(node);
if (index < view.Nodes.Count - 1)
{
view.Nodes.RemoveAt(index);
view.Nodes.Insert(index + 1, node);
}
}
}
}
Child节点将跟随他们的父母。
eDIT:添加的情况,即移动节点是TreeView中的根。当我觉得编写此代码是浪费时间,鉴于OP缺乏对评论的回应,我至少可以做的是如何修复Le-Savard的代码示例,以便将UP或UP的Muliple单击或上下文菜单上的下调选择...假设上下文菜单并非每次都被自动关闭,并且用户被迫一遍又一遍地选择相同的节点...创建非意外的副作用:
public static class Extensions
{
public static void MoveUp(this TreeNode node)
{
TreeNode parent = node.Parent;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index > 0)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index - 1, node);
// bw : add this line to restore the originally selected node as selected
node.TreeView.SelectedNode = node;
}
}
}
public static void MoveDown(this TreeNode node)
{
TreeNode parent = node.Parent;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index < parent.Nodes.Count - 1)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index + 1, node);
// bw : add this line to restore the originally selected node as selected
node.TreeView.SelectedNode = node;
}
}
}
}
,无论如何,限制儿童节点仅在其父节点节点集合中移动是一个
设计:设计选择可能非常适合一种解决方案。相似,这是一个
设计选择
强迫用户选择一个节点和上下文单击以获取上下文菜单,该菜单可以选择上下移动他们都想将其移动IT
:这不是一个:这不是一个:我会做出的设计选择:我将在此处使用拖放或允许在树上任何地方选择的任何选定节点的快速迁移重定位的按钮。通过我喜欢Dynami Le-Savard在这里使用扩展的方式。 这里是一种解决方案,可让您将节点拖动到任何想要的地方。要将节点移至与另一个节点相同的级别,请在丢弃节点时按住Shift。与替代方案及其潜在问题相比,这是一种非常简单的方法。示例是用更新版本的.NET(4.5)编写的。 注:请确保并在TreeView控件上= True = true,否则您将无法删除节点。
/// <summary>
/// Handle user dragging nodes in treeview
/// </summary>
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
/// <summary>
/// Handle user dragging node into another node
/// </summary>
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
/// <summary>
/// Handle user dropping a dragged node onto another node
/// </summary>
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
// Retrieve the client coordinates of the drop location.
Point targetPoint = treeView1.PointToClient(new Point(e.X, e.Y));
// Retrieve the node that was dragged.
TreeNode draggedNode = e.Data.GetData(typeof(TreeNode));
// Sanity check
if (draggedNode == null)
{
return;
}
// Retrieve the node at the drop location.
TreeNode targetNode = treeView1.GetNodeAt(targetPoint);
// Did the user drop the node
if (targetNode == null)
{
draggedNode.Remove();
treeView1.Nodes.Add(draggedNode);
draggedNode.Expand();
}
else
{
TreeNode parentNode = targetNode;
// Confirm that the node at the drop location is not
// the dragged node and that target node isn't null
// (for example if you drag outside the control)
if (!draggedNode.Equals(targetNode) && targetNode != null)
{
bool canDrop = true;
while (canDrop && (parentNode != null))
{
canDrop = !Object.ReferenceEquals(draggedNode, parentNode);
parentNode = parentNode.Parent;
}
if (canDrop)
{
// Have to remove nodes before you can move them.
draggedNode.Remove();
// Is the user holding down shift?
if (e.KeyState == 4)
{
// Is the targets parent node null?
if (targetNode.Parent == null)
{
// The target node has no parent. That means
// the target node is at the root level. We'll
// insert the node at the root level below the
// target node.
treeView1.Nodes.Insert(targetNode.Index + 1, draggedNode);
}
else
{
// The target node has a valid parent so we'll
// drop the node into it's index.
targetNode.Parent.Nodes.Insert(targetNode.Index + 1, draggedNode);
}
}
else
{
targetNode.Nodes.Add(draggedNode);
}
targetNode.Expand();
}
}
}
// Optional: The following lines are an example of how you might
// provide a better experience by highlighting and displaying the
// content of the dropped node.
// treeView1.SelectedNode = draggedNode;
// NavigateToNodeContent(draggedNode.Tag);
}
该版本扩展了原始版本,并允许您在父母之间移动子节点。
public static class Extensions
{
public static void MoveUp(this TreeNode node)
{
TreeNode parent = node.Parent;
TreeView view = node.TreeView;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index > 0)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index - 1, node);
}
else if (parent.PrevNode != null)
{
parent.Nodes.RemoveAt(index);
parent.PrevNode.Nodes.Add(node);
}
view.SelectedNode = node;
}
else if (node.TreeView.Nodes.Contains(node)) //root node
{
int index = view.Nodes.IndexOf(node);
if (index > 0)
{
view.Nodes.RemoveAt(index);
view.Nodes.Insert(index - 1, node);
view.SelectedNode = node;
}
}
}
public static void MoveDown(this TreeNode node)
{
TreeNode parent = node.Parent;
TreeView view = node.TreeView;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index < parent.Nodes.Count - 1)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index + 1, node);
}
else if (parent.NextNode != null)
{
parent.Nodes.RemoveAt(index);
parent.NextNode.Nodes.Insert(0, node);
}
view.SelectedNode = node;
}
else if (view != null && view.Nodes.Contains(node)) //root node
{
int index = view.Nodes.IndexOf(node);
if (index < view.Nodes.Count - 1)
{
view.Nodes.RemoveAt(index);
view.Nodes.Insert(index + 1, node);
view.SelectedNode = node;
}
}
}
}
thanks to dynami le savard for代码。 我添加了Moveleft和Moveright功能。