-
Visit Every Control on a Form (includes nested controls, no recursion)
C# version here.
This code will visit every control on a form, regardless of how deeply it's nested. You could have a TextBox in a Panel in a Splitter in a GroupBox in a TabPage in a TabControl in a Panel and it will still be found. No recursion is needed on your part, as this will simply follow the tab order from start to finish. It also doesn't matter if a control has it's TabStop set to False, as it must still have a TabIndex.
VB Code:
Dim ctl As Control = Me.GetNextControl(Me, True) 'Get the first control in the tab order.
Do Until ctl Is Nothing
'Use ctl here.
ctl = Me.GetNextControl(ctl, True) 'Get the next control in the tab order.
Loop
No doubt the GetNextControl method uses recursion internally, but that's not our concern. This will keep your code nice and neat and you'd need a very, very large number of controls before you'd notice a difference in performance.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
It seems it might not be able to see controls inside a ToolStripContainer, but I'll report back with further findings.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
You're correct, because the four ToolStripPanels and the ToolStripContentPanel are accessed via specific properties rather than the Controls collection. I think you'll find that the SplitContainer is in a similar situation.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
jmcilhinney, what about this:
vb Code:
For Each c As Control In Me.Controls
'Do something here
Next
Which is more efficient? I always use this if I want to find any control in my form. But I guess, For each method didn't order by tab control tough ...
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by michaelrawi
jmcilhinney, what about this:
vb Code:
For Each c As Control In Me.Controls
'Do something here
Next
Which is more efficient? I always use this if I want to find any control in my form. But I guess, For each method didn't order by tab control tough ...
Your code will visit the controls by z-order as opposed to tab order, but that's by-the-by. The point of my code is that it will visit nested controls too, while yours will only visit those controls parented directly by the form. Your code will not visit any controls that are nested within Panels, GroupBoxes, TabControls, etc.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
this will definitely come in handy... as always thanks
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by jmcilhinney
This code will visit every control on a form, regardless of how deeply it's nested. You could have a TextBox in a Panel in a Splitter in a GroupBox in a TabPage in a TabControl in a Panel and it will still be found. No recursion is need on your part, as this will simply follow the tab order from start to finish. It also doesn't matter if a control has it's TabStop set to False, as it must still have a TabIndex.
VB Code:
Dim ctl As Control = Me.GetNextControl(Me, True) 'Get the first control in the tab order.
Do Until ctl Is Nothing
'Use ctl here.
ctl = Me.GetNextControl(ctl, True) 'Get the next control in the tab order.
Loop
No doubt the GetNextControl method uses recursion internally, but that's not our concern. This will keep your code nice and neat and you'd need a very, very large number of controls before you'd notice a difference in performance.
Cool tip jmcilhinney,
When I think that all this time I have been using nested For Each to retrieve inner controls.:cry: Well no more from now on.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Greate Piece of code, no more recursive calls
thx man
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Very useful. In VS2008 it works for ToolStripContainers too. I have ToolStrips in ToolStripContainers in TabPages in a TabControl on a Form... no problem!
boops
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
this code can't find Menustrip and Submenus
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
That's because menu's aren't tab-able, even when you set the tab order, the menu's aren't given a number.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Thanks jm, I used it today.
Thanks for posting that.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
But what to do if we have to use only some controls???
it ll do action in all the controls :|
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by hacker786
But what to do if we have to use only some controls???
it ll do action in all the controls :|
My code allows you to visit every control on the form. It does NOT require you to do the something to every one of those controls. There's no reason you can test each control to see if it satisfies come criterion and then only perform your action if it does. You'll notice the word "if" appears in that last sentence a couple of times. That should give you a clue as to how you accomplish this.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
But i want to Reset all textbox from the form.
When i use this this ll reset all the controls.
thats u done
Bt wht i can do for this.
Blank all the textbox on the form ?
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
So... what's the problem? Inside the loop, check the control's type... if it is a text box, CType it and set its Text property to empty string.
-tg
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by hacker786
But i want to Reset all textbox from the form.
When i use this this ll reset all the controls.
thats u done
Bt wht i can do for this.
Blank all the textbox on the form ?
It seems to me that I already told you: only reset the control IF it's a TextBox:
vb.net Code:
If TypeOf ctl Is TextBox Then
ctl.ResetText()
End If
vb.net Code:
Dim txt As TextBox = TryCast(ctl, TextBox)
If txt IsNot Nothing Then
txt.ResetText()
End If
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Hmmm Okie
Thank you i got the clue :) and i ll done this thanx man :)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Thanks Jmci! Love it, use it all the time :)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Hi,
I'm trying to use this GetNextControl() function but I'm not sure how to do the declaration or definition for it. I keep getting an error that the method is not found. When I add the following definition:
Public Function GetNextControl(ctl as Control, forward as boolean) as Control
It says that I need an "End Function".
When I try to define it as a Declare statement it gives me an error also.
What is the correct function declaration I need to be able to use the GetNextControl() method in Visual Basic 6.0??
I'm trying to mimic the code that is posted at the beggining of this thread.
By the way I'm doing this because I inheret some visual basic application at work that now I have to maintain. The main form has a ton of controls, some of them hidden. I'm trying to make them all visible so I can see what they look like so I can understand the code. If someone has another way of achieveing this then let me know.
Thanks in advance for your input :-).
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
don't ... because you can't. Because there isn't an equivalent in VB6... it's new with .NET.
-tg
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Well that makes sense. Thanks for the quick response.
So, any ideas how I can find a hidden control in a VB6 form that I have no idea where it is?
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
nope... not with out thrid party add ons...
-tg
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Shouldn't this work?
Code:
for each ctl in me.controls
ctl.visible = true
next ctl
Edited: working from memory, so adapt syntax as needed! :D
-EM
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
works at run time... but at designtime, not so much... I think that's what nelg87 was looking for... something to help at design time.
-tg
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Thanks jmcilhinney , this is useful !
May I ask a simple question : I noticed you wrote :
ctl.ResetText
is it the same as ctl.Text = "" ?
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
iliekater
Thanks jmcilhinney , this is useful !
May I ask a simple question : I noticed you wrote :
ctl.ResetText
is it the same as ctl.Text = "" ?
If you place your mouse cursor over the word ResetText the intellesence will popup and tell you about it, or you can highlight commands,methods etc and press F1 to get more help on them.
F1..MSDN...
Control.ResetText Method
Resets the Text property to its default value.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Oh , so this applies to all types of controls ! This could be useful , thanks !
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
I tried this code in a little different fashion
'Calling Code
Code:
For Each tbp1 As TabPage In tabChannels.Controls
For Each ctl1 As Control In tbp1.Controls
If TypeOf ctl1 Is TabControl Then
ctl1.Enabled = True
For Each tbp2 As TabPage In ctl1.Controls
Select Case tbp2.Name
Case "tabParameter"
EnableDisableControls(tbp2)
Case "tabEquipment"
EnableDisableControls(tbp2)
End Select
Next
End If
Next
Next
'Called code
Code:
Private Sub EnableDisableControls(ByVal c As TabPage)
Try
EH.ErrorMessage = String.Empty
Do Until c Is Nothing
c = GetNextControl(c, True)
If TypeOf c Is TextBox Then
Dim txt As TextBox = DirectCast(c, TextBox)
txt.ReadOnly = True
ElseIf TypeOf c Is ComboBox Then
Dim cmb As ComboBox = DirectCast(c, ComboBox)
cmb.Enabled = False
End If
Loop
Catch ex As Exception
EH.ErrorMessage = "frmCalibration_3/EnableDisableControls() - " & ex.Message & "...Contact Engineering!" & "~E"
End Try
End Sub
I have a TabControl on my Windows Form. This TabControl contains 8 TabPages with each TabPage containing a UserControl which in turn contains many different controls.
In my code, I loop through each TabPage of the TabControl. The above routine is called only twice based on the name of the TabPages. As I stepped through the lines of code, it seems to be getting every TabPage within the TabControl rather than every control within the TabPage. Not sure what I'm doing wrong.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
@blakemckenna, the point of this code is to visit every control on a form. It doesn't seem like that is what you actually want. GetNextControl follows the Tab order and is not restricted to a specific container. If what you want is to visit every control on a TabPage then, assuming that all children are on the TabPage directly and not inside other containmers, you should simply loop through the Controls collection of that TablePage.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
That's what I normally do but your code looked tighter and made more sense! I will go back to what I had.
Thanks jmc!
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
jmcilhinney
@blakemckenna, the point of this code is to visit every control on a form. It doesn't seem like that is what you actually want. GetNextControl follows the Tab order and is not restricted to a specific container. If what you want is to visit every control on a TabPage then, assuming that all children are on the TabPage directly and not inside other containmers, you should simply loop through the Controls collection of that TablePage.
It doesnet work for toolstripmenu items or any non control
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
coolcurrent4u
It doesnet work for toolstripmenu items or any non control
That was basically addressed in post #4, i.e. this code will visit controls that are in a Controls collection of a control that is itself in a Controls collection, etc, all the way up to the form. If there is a break in the control/Controls chain then I don't think that GetNextControl can access it.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
jmcilhinney
That was basically addressed in post #4, i.e. this code will visit controls that are in a Controls collection of a control that is itself in a Controls collection, etc, all the way up to the form. If there is a break in the control/Controls chain then I don't think that GetNextControl can access it.
Is there any way to make it work for Toostripmenu, Datagridview columns, Toolstripmenuitem and ToolStripbutton?
because some of these are derived from Component Class
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
coolcurrent4u
Is there any way to make it work for Toostripmenu, Datagridview columns, Toolstripmenuitem and ToolStripbutton?
because some of these are derived from Component Class
This code relies on the GetNextControl method. That method, as the name suggests, gets the next control. Even then it relies on a direct hierarchy. It's certainly not going to get something that isn't a control. If you want to navigate a menu or a toolbar then you'd have to write code specific to that, which would almost certainly involve recursion..
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
vbfailure
Hello,
I have been looking for something like this, it seems ideal.
One thing I was curious about, does it actually loop through the controls in the order of the controls TabIndex? During a quick test it seems to loop through everything but in an order not following the TabIndex I have set on various controls.
Thanks!
The order of child controls in the parent's Controls collection matches the z-order. You can see this in the designer by using the Document Outline window.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
If you want to visit the controls by TabIndex then simply sort them by TabIndex.
vb.net Code:
Private Sub ProcessControl(ctrl As Control)
'Use ctrl here.
For Each child In ctrl.Controls.Cast(Of Control)().OrderBy(Function(c) c.TabIndex)
'Here be recursion. Arrrrrrr!
ProcessControl(child)
Next
End Sub
You can kick that off by calling the method and passing the form as an argument. If you don't want to process the form itself then change it to this:
vb.net Code:
Private Sub ProcessControls(ctrls As Control.ControlCollection)
For Each child In ctrls.Cast(Of Control)().OrderBy(Function(c) c.TabIndex)
'Use child here.
'Here be recursion. Arrrrrrr!
ProcessControl(child)
Next
End Sub
and pass the Controls property of the form to the first call. You can do whatever is appropriate in your specific scenario where it says "Use ctrl here" or "Use child here". Just be aware that sibling controls can have the same TabIndex and that code, as it is, ignores whether TabStop is set to False.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
That doesn't look like my code. Also, this is off-topic for this thread, which is about NOT using recursion. CodeBank threads, in particular, should not be cluttered up with tangential subjects. Please create your own thread in the appropriate forum to ask about this issue.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
I have made an API Proposal: Add Descendants property for Control for this. I you like it, please upvote it on github.com/dotnet/winforms.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
oliburg
I don't really see the point when you can just write an extension method to do it, e.g.
vb.net Code:
Imports System.Runtime.CompilerServices
Public Module ControlExtensions
<Extension>
Public Iterator Function GetControls(source As Control) As IEnumerable(Of Control)
Dim ctl As Control = source.GetNextControl(source, True) 'Get the first control in the tab order.
Do Until ctl Is Nothing
Yield ctl
ctl = source.GetNextControl(ctl, True) 'Get the next control in the tab order.
Loop
End Function
End Module
That is implemented using the same principle as the code in post #1 of this thread but you could opt for various other implementations too, e.g.
vb.net Code:
Imports System.Runtime.CompilerServices
Public Module ControlExtensions
<Extension>
Public Iterator Function GetControls(source As Control, Optional breadthFirst As Boolean = True) As IEnumerable(Of Control)
If breadthFirst Then
For Each child As Control In source.Controls
Yield child
Next
For Each child As Control In source.Controls
For Each descendent As Control In child.GetControls(breadthFirst)
Yield descendent
Next
Next
Else 'depthFirst
For Each child As Control In source.Controls
For Each descendent As Control In child.GetControls(breadthFirst)
Yield descendent
Next
Yield child
Next
End If
End Function
End Module
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
Quote:
Originally Posted by
jmcilhinney
I don't really see the point when you can just write an extension method to do it, [...]
Sure you can. That's what I explain in this SO post.
It would just be handy to have it built-in.
-
Re: Visit Every Control on a Form (includes nested controls, no recursion)
JM, I just wanted to let you know I've used this clever piece of code to thoroughly dispose user control classes in their near entirety. I like your style
Code:
If PanelMain.Controls.Count > 0 Then
Dim UC As UserControl = DirectCast(PanelMain.Controls(0), UserControl)
Dim ctl As Control = UC.GetNextControl(UC, True)
Do Until ctl Is Nothing
ctl.Dispose()
ctl = UC.GetNextControl(ctl, True)
Loop
UC.Dispose()
PanelMain.Controls.Clear()
End If