Saturday, 20 January 2007

Navigate a treeview with the tab key

Came across this post in an msdn forum and thought that cant be too hard, well its a little tricky which is why I have blogged it!


Firstly I created a form with the treeview and some nodes on it, and two buttons (you will see why soon!)


Then I tried plugging in to the key press event - however this doesnt fire when the tab button is pressed:( - however the previewkeypress event does:).


Now I need to get the tree node to expand when I click the tab button - a node has a nice .expand function so this was easy:)


This worked really well, apart from the fact that the tab button still tabbed to the next item! This means that the selected node changes, but the treeview loses focus. I fixed this by adding a boolean which is set to true if focus should be returned to the treeview, and simply checked it on the item after it, on the "enter" even I see if the boolean is set to true, and focus on the treeview if it is.


The final problem was caused by the shift button - if you press shift and tab users expect to go in the opposite direction to tab! thankfully the arguments to previewkeypress includes a .shift, so I simply went backwards, and used the same code on the button before the !

Screenshot:-



Here is the code:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

}

bool blnGrabFocus=false;

private void treeView1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
blnGrabFocus = false;//Used to pull focus back to the treeview after the tab
if (e.KeyValue == 9)//Stop on the tab keypress only
{
TreeNode oNode;
if (e.Shift)//Check to see if shift was held down
{//If it was navigate backwards
TreeNode oNodePrev = treeView1.SelectedNode.PrevNode;
if (oNodePrev != null)
{
oNodePrev.Expand();//Make sure you navigate the un-expanded previous nodes
}

oNode = treeView1.SelectedNode.PrevVisibleNode;//Set the node to the next previous(?!) node.
}
else//If we are tabbing forward
{
treeView1.SelectedNode.Expand();//expand the current node so child nodes will be itterated

oNode = treeView1.SelectedNode.NextVisibleNode;//Move to the next node
}
if (oNode == null)//If there isnt a next/previous node
{
blnGrabFocus = false;//Dont grad focus from the next item
}
else
{
treeView1.SelectedNode = oNode;//Set the next node
blnGrabFocus = true;//And grab focus
}
}
}
private void btnNextItem_Enter(object sender, EventArgs e)
{
if (blnGrabFocus)//Check to see if focus needs to be returned to the treeview
{
treeView1.Focus();//Return Focus
}
}

private void treeView1_Enter(object sender, EventArgs e)
{
blnGrabFocus = false;//Have focus back, release check
}

private void btnPreviousItem_Enter(object sender, EventArgs e)
{
if (blnGrabFocus)//Check to see if focus needs to be returned to the treeview
{
treeView1.Focus();//Return Focus
}
}
}
nice and easy:)


Ross

No comments: