简体   繁体   中英

Strange auto-collapse behaviour in a treeview when SelectedImageIndex is set?

In a treeview control, my default desired keyboard behaviour is using the left/right arrow keys to collapse/expand, and the up/down arrow keys to traverse visible nodes without collapsing or expanding them.

But for some strange reason, the following code automatically collapses/expands nodes when using the up/down arrow keys to select them:

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    // This line produces strange auto-collapse/expand behaviour,
    // but is needed in order to correctly set the image of the selected node.
    // If I comment this line out, then keyboard input produces the desired behaviour.
    treeView1.SelectedImageIndex = e.Node.ImageIndex;
}
  1. Why does this happen?
  2. How can it be prevented?

Actually, it is by design.

At the end of the documentation for the TreeView.SelectedImageIndex property:

When setting the SelectedImageIndex property at run time, the TreeView handle is recreated (see Control.RecreateHandle) to update the control's appearance. This causes all tree nodes to be collapsed, except for the selected TreeNode.

I reproduced the issue and realized that this happens only when the tree view's SelectedImageIndex is changed (Not when assigned, but when assigned to a different value). If you select a node with an ImageIndex 8 and then select another node with the same image index, this undesired behavior does not occur.

But; there is a solution anyhow. It is not perfect but can be improved.

The solution consists of keeping the expanded nodes in a custom collection and expanding them after the .SelectedImageIndex assignment, and only if the SelectedImageIndex is changed.

There are many workarounds in the code below. I will explain in comment lines when I have time, but maybe you can try it meanwhile.

    private List<TreeNode> expandedNodes = new List<TreeNode>();
    private TreeNode nodeAboutToCollapse;

    private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
    {
        // skip system calls
        if(e.Action == TreeViewAction.Unknown)
        {
            return;
        }

        if (treeView1.SelectedImageIndex == e.Node.ImageIndex)
        {
            nodeAboutToCollapse = null;
            return;
        }

        treeView1.SelectedImageIndex = e.Node.ImageIndex;

        for (int i = 0; i < expandedNodes.Count; i++)
        {
            if (expandedNodes[i] != nodeAboutToCollapse)
            {
                expandedNodes[i].Expand();
            }
        }
        nodeAboutToCollapse = null;
    }

    private void treeView1_AfterExpand(object sender, TreeViewEventArgs e)
    {
        if (!expandedNodes.Contains(e.Node))
        {
            expandedNodes.Add(e.Node);
        }
    }

    private void treeView1_AfterCollapse(object sender, TreeViewEventArgs e)
    {
        expandedNodes.Remove(e.Node);
        nodeAboutToCollapse = null;
    }

    private void treeView1_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
    {
        nodeAboutToCollapse = e.Node;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM