Question How do I give focus to a form displayed in a split container

robertb_NZ

Well-known member
Joined
May 11, 2010
Messages
146
Location
Auckland, New Zealand
Programming Experience
10+
I have a form with a splitcontainer. The left panel contains a Treeview: when a node of this is selected a form is displayed in the right panel. Here is typical code for one of the cases: -
ElseIf Action = "NewCICS" Then
Dim frm As New NewCICS
frm.TopLevel = False
frm.Parent = Me.SplitContainer1.Panel2
' Size the parent window so that NewCICS fits
SplitContainer1.Height = frm.Height
SplitContainer1.SplitterDistance = trvTemplates.Width
SplitContainer1.FixedPanel = FixedPanel.Panel1
SplitContainer1.Width = trvTemplates.Width + frm.Width
Me.Width = SplitContainer1.Width
' Display NewCICS
frm.BringToFront()
frm.Show()

This all works perfectly except for one detail: when the form is displayed the focus remains on the selected Treeview node, and you have to either click or tab to move to the first input field in the NewCICS child window. How can I have this happen automatically? I've tried adding frm.focus() either before or after frm.show(), neither makes any difference.
 
If you've read the documentation then you know that you shouldn't be calling Focus at all. The documentation clearly states:
MSDN said:
Focus is a low-level method intended primarily for custom control authors. Instead, application programmers should use the Select method or the ActiveControl property for child controls, or the Activate method for forms.
Because you are using the form as a child control, I'm not sure which will work in this case but, with only two choices, it shouldn't be hard to work out.

That said, you probably shouldn't be using a SplitContainer at all. If you just made the parent form an MDI parent then your child forms would work normally. You could add your own drag and drop code to be able to expand and collapse a Panel at the side of the parent or use a control that works the way the tool windows around VS work.
 
Thank you for trying to help. I tried adding frm.Activate, frm.Select, and finally Me.ActiveControl = frm.txtProgramName after frm.show (I also tried these before frm.show, in case that made a difference), but nothing made any difference at all. I'll try your suggestion of using an MDI parent: I hadn't done this because a splitcontainer gives me the behavior I want elsewhere in the form and there is no warning that splitcontainers with child forms exhibit anomalous behavior.

By the way, you should be careful about comments like "If you've read the documentation then you know that you shouldn't be calling Focus at all. The documentation clearly states...", especially with a faulty reply. In fact I'd spend quite a lot of time searching documentation before I gave up and created a post but I hadn't come across this, and (as you'll see if you Google "vb.net focus") most authors seem unaware that focus is intended only for custom controls. Your comment reminds me of the scene in "The Hitchhiker's Guide to the Galaxy" where Arthur Dent complains that nobody has warned the Earth's inhabitants that it is about to be demolished for a hyperspace highway, only to be told by the Vogons that a notice had been properly published in a locked pillbox on a planet orbiting Alpha Centauri.

Thank you for your help. I'll post again if/when I find something that works.
 
If I had to guess, which I do, I'd say that you can't focus a form when used in that manner. You probably have to focus a control on the form. I haven't tested that theory because I've never used a form in this manner, nor would I.
 
Just wondering, since you're using the form as a control, why don't you design it as a UserControl instead of a Form?

Also, selecting the input control makes sense, setting ActiveControl or using Select method does the same here. The problem here however is the TreeView.AfterSelect event, which won't release focus from the selected treenode, a simple workaround it to use Control.BeginInvoke method to make the selection happen after the AfterSelect event is finished processing. Example:
Me.BeginInvoke(New MethodInvoker(AddressOf frm.txtProgramName.Select))
 
Thank you John, your suggestion about BeginInvoke ... worked perfectly.

The reason that I didn't use a UserControl is simple: I didn't think of it. I've used UserControls a lot in ASP.NET development, but rarely in VB.NET, and I didn't think of it here because I didn't start by thinking "This is something that I want on several forms", I started with "I want to put a form here", and Google took me to this article show form into splitcontainer.panel - Visual Basic .NET and it was all very simple. Anyway, I guess that if I changed to a user control I wouldn't have solved the problem because it is with TreeView.AfterSelect?

BTW, in the ASP.NET forums I'm used to clicking "Mark as Answer" to give you credit and to direct later readers to the useful posts within the threads. I can't see a way of doing this here - do I have an incorrect forum setting?

Thank you, Robert.
 
Thanks jcilhinney, I'd previously tried this (and a number of other variations). JohnH had the answer: TreeView.AfterSelect isn't releasing focus, and the answer is to use BeginInvoke. However thank you for suggesting other approaches, particularly MDI forms. While that is not what I want here, it is the correct answer at the next form level above this one, so I will have to research this as I've never written an MDI form. Which tutorials on MDI forms do you recommend?
 
BTW, in the ASP.NET forums I'm used to clicking "Mark as Answer" to give you credit and to direct later readers to the useful posts within the threads. I can't see a way of doing this here - do I have an incorrect forum setting?
Below each post is a "Like" you can click, likes are shown so users can see them when they read the thread, and could indicate a post has good value.

There is also star icon below each post that says "Add to this user's reputation", this adds to the Reputation score of a user and can be seen in post header in all posts of that user (both as indicator bar and rep point value), this indicates the accumulated 'weight' of a user in general.

Threads can be marked as solved by editing (advanced) first post in thread and changing thread prefix to "Resolved" or "Answered", this is shown in thread listings where that thread appear and even in external search engines such as Google.
 
Anyway, I guess that if I changed to a user control I wouldn't have solved the problem because it is with TreeView.AfterSelect?
Correct, I tested that also, same behaviour regarding AfterSelect. I would change those "forms" into user controls though.
 
Back
Top