Tree control focus frustration

A

Andrew Lighten

Hi;

I've built the guts of an explorer style application in C#. It has a
tree view on the left showing a series of nodes that are relevant to my
user, and as they click on each one, the right-hand side of my window
shows the particular panel that's relevant to the selected node.

I have one minor frustration, however. What I'd like to do is focus on
the first control within the newly chosen panel. I know which control
this is, and I can transfer focus to it by Select()'ing it, but once the
tree control has finished its AfterSelect() event it steals focus back
again.

I've got a dual monitor setup and I can step through my tree control's
AfterSelect() event handler. My new panel is selected, completely drawn
by calling Update(), the first control on the panel is selected and
focused on and the tree loses focus. Finally, when I step off the end of
AfterSelect(), focus magically snaps back to the tree.

I'd really like focus to stay on my newly selected panel rather than the
tree.

(1) Am I fighting a pointless battle here? Should focus stay with the tree?

(2) If it's not extremely rude to move focus to the new panel and leave
it there, how do I do it?

Thanks,
Andrew.
 
S

Stephany Young

I've just had a long battle with this myself.

If you put some code in a GotFocus event handler for the TreeView you will
see that the Treeview does indeed 'grab' the focus back but only if the
focus is transferred to another control while the AfterSelect event handler
is cancelled.

It possibly happens in a similar fashion in other event handlers for the
TreeView but I haven't bothered to test any others.

What is happening is that, while the AfterSelect event handler is active,
after transferring the focus to wherever, the execution point returns to the
AfterSelect event handler and, as far as I can figure out, something in
TreeView decides that it is has lost the focus and grabs it back. This
causes the GotFocus event to fire when the AfterSelect event handler
finishes.

Whether this is by design or not, I have no idea. From my point of view it
is bug. In VB6, if one transferred the focus to another control while the
NodeClick event handler was active, then the VB6 TreeView did not 'grab' the
focus back and I see no reason why the .Net implementation should behave any
differently. If anyone has any more information on this I would be
interested to hear.

I suppose you might say that I am a bit miffed with the AfterSelect event
because it works differently from the NodeClick event in VB6. In VB6 the
NodeClick event fired when you clicked on a node regardless whether that
node was already selected or not. The AfterSelect event only fires when you
click on a node that is not already selected.

The problem for me was how to make the AfterSelect event to behave like the
VB6 NodeClick event and also to solve the 'problem' of the focus being
returned to the TreeView. This is what works for me. It is not very pretty
but it is reliable.

Private m_showform As Form = Nothing

Private Sub tvMenu_AfterSelect(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.TreeViewEventArgs) Handles tvMenu.AfterSelect

If Not IsNothing(e.Node.Tag) Then
Dim f As Form = UseLoadedForm(e.Node.Tag)
Select Case e.Node.Tag()
Case "fProjectMaint"
If IsNothing(f) Then
f = New fProjectMaint
f.MdiParent = Me
f.Show()
m_showform = f
Else
m_showform = f
tvMenu_GotFocus(tvMenu, New System.EventArgs)
End If
Case "fReportParam"
If IsNothing(f) Then
f = New fReportParam
f.MdiParent = Me
f.Show()
m_showform = f
Else
m_showform = f
tvMenu_GotFocus(tvMenu, New System.EventArgs)
End If
End Select
End If

End Sub

Private Sub tvMenu_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles tvMenu.Click

Dim tn As TreeNode =
tvMenu.GetNodeAt(tvMenu.PointToClient(Cursor.Position))

If Not (tn Is Nothing) Then
If tn Is tvMenu.SelectedNode Then
tvMenu_AfterSelect(tvMenu, New
System.Windows.Forms.TreeViewEventArgs(tvMenu.SelectedNode))
Else
tvMenu.SelectedNode = tn
End If
End If

End Sub

Private Sub tvMenu_GotFocus(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles tvMenu.GotFocus

If Not IsNothing(m_showform) Then
m_showform = Nothing
SendKeys.Send("{TAB}")
End If

End Sub

In the Click event handler we determine which node was clicked. If the
control was clicked while the mouse pointer was not on a node (line) then
the result is Nothing. We then determine if the clicked node is currently
selected. If so then execute the code in the AfterSelect event handler
otherwise make the clicked node the selected node thus allowing the
AfterSelect event to fire normally.

In the AfterSelect event handler we do our bit of magic. In this example we
open an MDI Child form if it is not already open. If it is already open we
transfer the focus to it. Either way we set a variable and make sure that
the GotFocus code is executed.

In the GotFocus event, if the variable is set, we reset it and simulate a
press of the Tab key, thus moving the focus back to where we want it.

I do not purport that this is the only 'workaround'.
 
A

Andrew Lighten

Stephany said:
I've just had a long battle with this myself.

If you put some code in a GotFocus event handler for the TreeView you will
see that the Treeview does indeed 'grab' the focus back but only if the
focus is transferred to another control while the AfterSelect event handler
is cancelled.

....

Thanks, Stephany. I kinda feel it's a bug as well. Your workaround sure
does look like a whole lot of gymnastics for something that should just
work. I'll have a look at applying it and see how I go...
 
Joined
Jun 24, 2006
Messages
1
Reaction score
0
A possible solution...

private delegate void AsyncDelegate();

void
treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
this.BeginInvoke(new AsyncDelegate(SetFocusElsewhere));
}

private void SetFocusElsewhere()
{
MyControl.Focus();
}

Hope this helps, sorry its not in VB. Suga.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top