Reputation: 1825
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;
}
Upvotes: 0
Views: 484
Reputation: 7187
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;
}
Upvotes: 2