Excaping recursive functions

G

Guest

Hi Everyone,
I got the following code from Deborah Kurata's book. I need to return the
control that matches the name that I pass into the function. It does iterate
through the form but it will not return a control reference. Following the
code, it does actually get a reference, but when it returns from one of the
recursize calls, the code keeps going. For examle:
First call to FinControl
Has child so call FindControl again
Finds control, returns the reference
'Comment I need a garnteed way of exiting now
Keeps looping, and if a control has child again, call FindControl again

Private Function FindControl( ByVal ControlName As String, ByVal CurrentForm
As control) As Control
Dim rtn As Control
For Each ctrl As Control In CurrentForm.Controls
If ctrl.Name = Controlname then
rtn = ctrl
exit For
End If
If ctrl.HasChildren then
FindControl(ControlName, ctrl)
End If
Next ctrl
return rtn
End Function

What is the best way to handle this one. Thanks for any info.
Michael
 
J

Jay B. Harlow [MVP - Outlook]

Michael,
I would expect:

| If ctrl.HasChildren then
rtn = FindControl(ControlName, ctrl)
Exit For
| End If

However I would not define the rtn variable, I would simply use the Return
statement when I found an item. Something like:

| Private Function FindControl( ByVal ControlName As String, ByVal
CurrentForm
| As control) As Control
| For Each ctrl As Control In CurrentForm.Controls
| If ctrl.Name = Controlname then
Return ctrl
| End If
| If ctrl.HasChildren then
Return FindControl(ControlName, ctrl)
| End If
| Next ctrl
Return Nothing
| End Function

However some developer's prefer not to use the above, as they consider it
"multiple return points"...

Hope this helps
Jay

| Hi Everyone,
| I got the following code from Deborah Kurata's book. I need to return the
| control that matches the name that I pass into the function. It does
iterate
| through the form but it will not return a control reference. Following the
| code, it does actually get a reference, but when it returns from one of
the
| recursize calls, the code keeps going. For examle:
| First call to FinControl
| Has child so call FindControl again
| Finds control, returns the reference
| 'Comment I need a garnteed way of exiting now
| Keeps looping, and if a control has child again, call FindControl again
|
| Private Function FindControl( ByVal ControlName As String, ByVal
CurrentForm
| As control) As Control
| Dim rtn As Control
| For Each ctrl As Control In CurrentForm.Controls
| If ctrl.Name = Controlname then
| rtn = ctrl
| exit For
| End If
| If ctrl.HasChildren then
| FindControl(ControlName, ctrl)
| End If
| Next ctrl
| return rtn
| End Function
|
| What is the best way to handle this one. Thanks for any info.
| Michael
|
 
S

Stephany Young

I think that Jay might have got it slightly wrong.

In the original procedure, if the target control was 'top level' then I
would expect the procedure to find it and return a reference to it:

For Each ctrl As Control In CurrentForm.Controls
If ctrl.Name = Controlname Then
rtn = ctrl
Exit For
End If
...
Next ctrl
Return rtn

However, once a recursive call is made, the result is being 'thrown away',
the loop will continue and the symptoms as described will be exhibited:

...
If ctrl.HasChildren Then
FindControl(ControlName, ctrl) <--- The result from this call is not
assigned to anything
End If

My take on it is:

Private Function FindControl( ByVal ControlName As String, ByVal
CurrentForm As control) As Control

Dim rtn As Control

For Each ctrl As Control In CurrentForm.Controls
If ctrl.Name = Controlname Then
rtn = ctrl
Exit For
End If
If ctrl.HasChildren Then
rtn = FindControl(ControlName, ctrl)
If Not (rtn Is Nothing) then Exit For
End If
Next ctrl

Return rtn

End Function

The check for Not Nothing is important otherwise the loop will continue to
the end of the 'children', control will drop through the end of the loop and
Nothing will be returned regardless of whether we found it or not. The early
exit when we find it in a recursive call corrects this oversight.
 
C

Cor Ligthert

Michael,

I am fond of those recursive ones. An alternative

\\\\
Private Function ControlName(ByVal parentCtr As Control, _
ByVal NameString As String) As Control
If ControlName Is Nothing Then
Dim ctr As Control
For Each ctr In parentCtr.Controls
If ctr.Name = NameString Then
Return ctr
Else
Dim getControl As Control = ControlName(ctr, NameString)
If Not getControl Is Nothing Then Return getControl
End If
Next
Else
Return ControlName
End If
End Function
///

I don't say this one is better.

Cor
 
H

Herfried K. Wagner [MVP]

Michael said:
I got the following code from Deborah Kurata's book. I need to return the
control that matches the name that I pass into the function. It does
iterate
through the form but it will not return a control reference. Following the
code, it does actually get a reference, but when it returns from one of
the
recursize calls, the code keeps going.

Accessing controls by their names or indices
<URL:http://dotnet.mvps.org/dotnet/faqs/?id=controlbynameindex&lang=en>
 
J

Jay B. Harlow [MVP - Outlook]

Stephany,
| rtn = FindControl(ControlName, ctrl)
| If Not (rtn Is Nothing) then Exit For

That makes more sense... It was one of those answers I didn't verify first
;-)

Thanks
Jay


|I think that Jay might have got it slightly wrong.
|
| In the original procedure, if the target control was 'top level' then I
| would expect the procedure to find it and return a reference to it:
|
| For Each ctrl As Control In CurrentForm.Controls
| If ctrl.Name = Controlname Then
| rtn = ctrl
| Exit For
| End If
| ...
| Next ctrl
| Return rtn
|
| However, once a recursive call is made, the result is being 'thrown away',
| the loop will continue and the symptoms as described will be exhibited:
|
| ...
| If ctrl.HasChildren Then
| FindControl(ControlName, ctrl) <--- The result from this call is not
| assigned to anything
| End If
|
| My take on it is:
|
| Private Function FindControl( ByVal ControlName As String, ByVal
| CurrentForm As control) As Control
|
| Dim rtn As Control
|
| For Each ctrl As Control In CurrentForm.Controls
| If ctrl.Name = Controlname Then
| rtn = ctrl
| Exit For
| End If
| If ctrl.HasChildren Then
| rtn = FindControl(ControlName, ctrl)
| If Not (rtn Is Nothing) then Exit For
| End If
| Next ctrl
|
| Return rtn
|
| End Function
|
| The check for Not Nothing is important otherwise the loop will continue to
| the end of the 'children', control will drop through the end of the loop
and
| Nothing will be returned regardless of whether we found it or not. The
early
| exit when we find it in a recursive call corrects this oversight.
|
|
| | > Michael,
| > I would expect:
| >
| > | If ctrl.HasChildren then
| > rtn = FindControl(ControlName, ctrl)
| > Exit For
| > | End If
| >
| > However I would not define the rtn variable, I would simply use the
Return
| > statement when I found an item. Something like:
| >
| > | Private Function FindControl( ByVal ControlName As String, ByVal
| > CurrentForm
| > | As control) As Control
| > | For Each ctrl As Control In CurrentForm.Controls
| > | If ctrl.Name = Controlname then
| > Return ctrl
| > | End If
| > | If ctrl.HasChildren then
| > Return FindControl(ControlName, ctrl)
| > | End If
| > | Next ctrl
| > Return Nothing
| > | End Function
| >
| > However some developer's prefer not to use the above, as they consider
it
| > "multiple return points"...
| >
| > Hope this helps
| > Jay
| >
| > | > | Hi Everyone,
| > | I got the following code from Deborah Kurata's book. I need to return
| > the
| > | control that matches the name that I pass into the function. It does
| > iterate
| > | through the form but it will not return a control reference. Following
| > the
| > | code, it does actually get a reference, but when it returns from one
of
| > the
| > | recursize calls, the code keeps going. For examle:
| > | First call to FinControl
| > | Has child so call FindControl again
| > | Finds control, returns the reference
| > | 'Comment I need a garnteed way of exiting now
| > | Keeps looping, and if a control has child again, call FindControl
again
| > |
| > | Private Function FindControl( ByVal ControlName As String, ByVal
| > CurrentForm
| > | As control) As Control
| > | Dim rtn As Control
| > | For Each ctrl As Control In CurrentForm.Controls
| > | If ctrl.Name = Controlname then
| > | rtn = ctrl
| > | exit For
| > | End If
| > | If ctrl.HasChildren then
| > | FindControl(ControlName, ctrl)
| > | End If
| > | Next ctrl
| > | return rtn
| > | End Function
| > |
| > | What is the best way to handle this one. Thanks for any info.
| > | Michael
| > |
| >
| >
|
|
 

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

Top