2
votes

I'm having an issue with the selected node in a treeview.

Here is are two scenario. (# 2 is causing my problem)

1 - If I select the node "level", press F2, change the label and press enter. The selectedNode inside the AfterLabelEdit will change. The selectedNode will change from "Level1" to "Root".

2 - If I select the node "level", press F2, change the label but click somewhere on the treeview, the selectedNode will never change.

Is an event firing that is causing the issue?

I've created a small test project to show the issue at hand.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.Load += new EventHandler(Form1_Load);
        this.treeView1.KeyDown += new KeyEventHandler(Form1_KeyDown);
        this.treeView1.AfterLabelEdit += new NodeLabelEditEventHandler(treeView1_AfterLabelEdit);
    }

void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
    Console.WriteLine(this.treeView1.SelectedNode);
    this.treeView1.SelectedNode = this.treeView1.SelectedNode.Parent;
    Console.WriteLine(this.treeView1.SelectedNode);
    TreeNode test = this.treeView1.SelectedNode;
}

void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (this.treeView1.SelectedNode != null)
    {
        if (e.KeyData == Keys.F2)
        {
            this.treeView1.SelectedNode.BeginEdit();
        }
    }

    base.OnKeyDown(e);
}

void Form1_Load(object sender, EventArgs e)
{
    this.treeView1.Nodes.Add(new TreeNode("root"));
    this.treeView1.Nodes[0].Nodes.Add(new TreeNode("level1"));

    this.treeView1.Nodes[0].Nodes[0].Nodes.Add(new TreeNode("level2"));
    this.treeView1.SelectedNode = this.treeView1.Nodes[0];
    this.treeView1.SelectedNode.ExpandAll();
    this.treeView1.SelectedNode = this.treeView1.Nodes[0].Nodes[0];
}

}

2

2 Answers

3
votes

It is an event order problem, the mouse click fires after AfterLabelEdit so it wins. The typical BeginInvoke trick doesn't work, you'll need a Timer to select the node:

    void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) {
        TreeNode nextnode = this.treeView1.SelectedNode.Parent;
        var timer = new Timer() { Enabled = true, Interval = 50 };
        timer.Tick += delegate {
            this.treeView1.SelectedNode = nextnode;
            timer.Dispose();
        };
    }

That works, kinda ugly. This only happens when the user clicks a specific node, maybe you should not override the choice. Kudos for the repro code btw.

1
votes

Kinda a hack, but this will select the root node when the user clicks somewhere else in the treeview, except for the level2 node:

private bool SelectParent = false;
void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
    this.treeView1.SelectedNode = e.Node.Parent;
    SelectParent = true;
}

    private void treeView1_MouseDown(object sender, MouseEventArgs e)
    {
        if (SelectParent)
        {
            this.treeView1.SelectedNode = this.treeView1.SelectedNode.Parent;
            SelectParent = false;
        }

    }

put this in your form1 constructor:

    this.treeView1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.treeView1_MouseDown);