-1

I have overridden the TreeView events BeforeSelect and AfterSelect. Both get called when clicking on a node in the tree. You can see in the code below that I'm outputting the name of the tree node in each method. Suppose the tree looks like so:

UpperNode1
--LowerNode1a
--LowerNode1b
UpperNode2
--LowerNode2a
--LowerNode2b

and suppose LowerNode1a is currently selected. When clicking then on LowerNode1b, eventArgs.Node.Name is "LowerNode1b" in both methods. I was hoping that in the BeforeSelect, that eventArgs.Node.Name would be "LowerNode1a" because I wanted to do some work on that node upon leaving it. How can I do this?

private void trv_BeforeSelect(object sender, TreeViewCancelEventArgs eventArgs)
{
    System.Diagnostics.Trace.WriteLine("trvApproval_BeforeSelect(): eventArgs.Node.Name: " + eventArgs.Node.Name);
}

private void trv_AfterSelect(object sender, TreeViewEventArgs eventArgs)
{
    System.Diagnostics.Trace.WriteLine("trvApproval_AfterSelect(): eventArgs.Node.Name: " + eventArgs.Node.Name);
}

Edit:
The sender parameter is a TreeView object. Unfortunately SelectedNode is null. Strangely, there is a member prevHoveredNode (which has a valid value even) but not a prevSelectedNode.

Al Lelopath
  • 6,448
  • 13
  • 82
  • 139

2 Answers2

1

You can just use the SelectedNode property of the TreeView inside the BeforeSelect event.

treeView1.BeforeSelect += (s, e) =>
{
    var selected = treeView1.SelectedNode;
    var next = e.Node;
};

if UpperNode1 was selected and you click LowerNode1a then UpperNode1 is selected and LowerNode1a is next

Al Lelopath
  • 6,448
  • 13
  • 82
  • 139
Blake Thingstad
  • 1,639
  • 2
  • 12
  • 19
1

You are using the incorrect events. Those events are meant to do things if a TreeNode is selected. With BeforeSelect you can indicate that you don't allow this selection, with AfterSelect you can decide what to do with the selected TreeNode once if has been selected.

However, you don't want to do anything with the selected TreeNode, you want to do something with the item that this selected TreeNode stands for. In fact, if it wasn't a TreeView, but another class in which you could select items, you'd want your code still to work.

Therefor, you need an event that is called when an Item is selected. Microsoft forgot that, and you'll see that they added it later in System.Windows.Control.SelectedItemChanged See also why isn't there a SelectedNodeChange for TreeView?

Alas this doesn't help you. The neat thing would be to derive a class from TreeView, so you could use for other purposes in future. If you are sure you will only do this once, don't derive, do it in your destination class

class MyTreeView : System.Windows.Forms.TreeView
{
    public TreeNode SelectedNode {get; set;}

    protected override void OnAfterSelect(TreeViewEventArgs e)
    {
         // raise event that previous node is DeSelected
         if (this.SelectedNode != null)
         {
             this.OnNodeDeselected(e.Action);
         }
         if (e.Node != null && e.Node.IsSelected)
         {
             this.OnNodeSelected(e);
         }
    }

    protected virtual void OnNodeDeselected(TreeViewAction action)
    {
         TreeViewEventArgs eventArgs = new TreeViewEventArgs(this.SelectedNode, action);
         // TODO: raise deselect event
         this.SelectedNode = null; // nothing selected anymore
    }

    protected virtual void OnNodeSelected(TreeViewEventArgs e)
    {
        // TODO: raise event to indicate a node has been selected
        this.SelectedNode = e.Node
    }
}
Al Lelopath
  • 6,448
  • 13
  • 82
  • 139
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
  • On the `public TreeNode SelectedNode {get; set;}` I get the warning `... Hides inherited member 'TreeView.SelectedNode' Use the new keyword if hiding was intended`. It seems to work just fine as is. Would you recommend adding the `new` keyword? – Al Lelopath Oct 31 '17 at 17:55
  • 1
    No. Apparently a Treeview already has a property SelectedNode. Look up what it stands for. Does it have the value you were looking for? Does it have an event if if changes? If not, could you use OnNodeSelected to notify others that this already existing SelectedNode changed. Consider event OnSelectedNodeChanged – Harald Coppoolse Oct 31 '17 at 19:51