views:

380

answers:

2

What is the most accurate way to move a node up and down in a treeview. I got a context menu on each node and the selected node should be moved with all its subnodes.

I'm using C# .Net 3.5 WinForms

+3  A: 

You can use the following extensions :

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 nodes will follow their parents.

EDIT: Added case that node to move is a root in the TreeView.

Dynami Le Savard
Brother Dynami, I am delighted you took at least one thing I said seriously :) best,
BillW
+1  A: 

While I feel writing this code is a waste of time, given the lack of response to comments by the OP, the least I can do is show how the code example by Le-Savard can be fixed so that muliple clicks of the up or down choice on the context menu ... assuming the context menu is not auto-closed each time and the user is forced to select the same node over and over again ... will do the right thing with the orignally selected node, and not create un-intended side effects :

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;
            }
        }
    }
}

Of course this fix, still does not address the fact that in the example code that multiple root nodes cannot be moved (since they are 'parentless) : that's easiliy fixable.

Nor does it address the more interesting case where moving up a top child-node means you make some interpretation of where that "promoted" child code should go : exactly the same "strategic choice" is involved where you "move down" the last child node of a parent node and are thus required to decide where it should go. In Dynami Le-Savard's code : these cases are just ignored.

However, it is a design-choice to restrict child node from only being moved within their parent nodes Nodes collection : a design choice that may be perfectly suitable for one solution.

Similarly, it is a design choice to force a user to select a node and context-click to get a context menu that allows a choice of moving up or down every single time they want to move it : that's not a design choice I'd make : I'd be using drag-and-drop here or buttons that allow repeated rapid-fire relocation of any selected node anywhere in the tree.

By the way I like Dynami Le-Savard's use of extensions here.

BillW
Hm, interesting. You managed to deduct, from OP's vague 2 lines of description, that : 1-The context menu is actually the thing containing the MoveUp() and MoveDown() functionalities; 2-The request was actually to move nodes through their indentation levels, instead of among their siblings; 3-The software user was actually doing the action of moving nodes up and down, instead of it being a underlaying, automated action. I mean at that point, why stop there, let's add shiny fluid transitions that moves the node smoothly into position, maybe even add a couple of flips and pretty bright sparks.
Dynami Le Savard
Brother Dynami, we're both "using psychic powers" here, given lack of response by OP to reasonable questions about what they intended :) I apologize if anything I said above seems critical of your answer. The fact is your answer will have a bizarre side effect once the moved node gets to the top of its sibling order, and "move up" is repeated. If you pointed out, or corrected, such a behavior in code I published, I would be happy, and vote you up :) As I said, I like the way you used extension methods here ! And I enjoyed the poetic creativity in your "send up" of my response !
BillW
1. selecting a move-up or move-down of the node via the context menu is the only reasonable assumption you can make here : of course that will trigger code that is "underlying" (where else would it "lie" ?). 2. I assumed nothing about moving the node through indentation levels : I just raised the question to try and get the OP to make a clear statement about exactly what they were doing : I raised the issue : I did not say that issue had to be addresed. 3. With a context menu choice who else but the end user would be making the choice to move the node up or down : the Wizard of Oz :) ?
BillW
Not exactly sure I'm understanding the bizarre side effect. Anyhow, what I do know is that I, like you, interpreted the question in my own way, and posted an answer in consequence. If the OP wasn't satisfied with the proposition, I would assume he would have reacted in consideration. To be honest, his context was simply not explained enough to go beyong simple node permutations among siblings without ample assumptions, so I wrote just that, and waited for his reaction.
Dynami Le Savard