Iterate through controls on form in design view...

  • Thread starter Thread starter Jan Nielsen
  • Start date Start date
J

Jan Nielsen

Hi
In Microsoft Access it is possible to write code like this

Sub test()
DoCmd.OpenForm "TestForm", acDesign
Dim a As Control
For Each a In Forms("TestForm").Controls
Do stuff
Next
End Sub

To iterate through all controls on a form at DESIGN time. This will then
take effect for the form at runtime.

Is this possible in VB.Net?


Best regards

Jan
 
Hi Jan,

I'm a bit confused by what you mean by doing stuff at design-time to take
effect at run-time so the following is more for info than to answer your
query.

In .NET a Control's constructor is called both at design-time and (of
course) at run-time. There is a flag, Control.DesignMode which tells you
which.

If you want to do something for literally <all> the Controls on the Form,
you'll have to have a recursive method which takes a Control as a parameter
and does something for each of its contained Controls and so on for theirs. (A
Form is a Control so no problem getting it all started).

Class Foo As Form
Public Sub New()
MyBase.New()
InitializeComponent()
If Me.DesignMode Then
DoStuffToControls (Me)
End If
End Sub

Sub DoStuffToTheControlsOf (oControl As Control)
For Each oChildControl in oControl.Controls
Do stuff to oChildControl
DoStuffToTheControlsOf (oChildControl)
Next
End Sub

Regards,
Fergus
 
Hi Fergus
Thanks for your answer.
What I meant was that you can move create a form and place some controls on
it. Then "normally" af runtime the controls will be placed at the same place
as at design time. But you can move the controls via code and then the
design view and the runtime view are different.

What I would like to do was to edit properties in design time via code (ie
size of all textboxes)
Thus permanently changing the look of the form in design view.

Your code confuses me a bit:
You seem to have two different functions
DoStuffToControls
and
DoStuffToTheControlsOf
Should this be the same function?
Also in
Sub DoStuffToTheControlsOf (oControl As Control)
For Each oChildControl in oControl.Controls
Do stuff to oChildControl
DoStuffToTheControlsOf (oChildControl)
Next
End Sub

Where do you define the oChildControl?


Best regards

Jan
 
Hi again Fergus
I also do not see how you call the function.
If I hit F5 the form is not in design mode anylonger.

Best regards

Jan
 
Hi Jan,

The two names should be the same - that's an oops on the editing - so you
call it from Sub New() as shown.

oChildControl is, guess what, a Control!! ;-)

When you hit F5 I would certainly hope that you are no longer in Design
mode! But why does this matter?

!! What I would like to do was to edit properties in design time
!! via code (ie size of all textboxes)
!! Thus permanently changing the look of the form in design view.

I'm afraid this still makes no sense to me. Do you mean that you want, for
example, all TextBoxes to be 200 pixels wide, regardless of the setting in the
properties box? If so, why would you want this at design time but not at run
time?? Or do you want it for both? What is supposed to happen if you drag a
new TextBox onto the Form?

!! But you can move the controls via code and then the
!! design view and the runtime view are different.

Could you say what you actually want to do because I'm finding it hard to
create an imaginary situation.

Regards,
Fergus
 
Hi again Fergus
Thanks for your time
I will try to explain further.

I wanted to move all my controls on my form up 23 pixels if the
Control.Location.Y was bigger than 150
Something like
if MyControl.Location.Y > 150 then mycontrol.location.Y -= 23

I can do this at runtime (which means that my form has a different look in
design time than it has in runtime).
But I would like to do this in code while the form is in Design mode. This
should free me from moving the controls manually with the mouse or using the
Properties Window.

Hope this makes sense.

Jan
 
Hi Jan,

I understand now. You want to be doing this at design-time <and> at
run-time. In this case there's no need for checking DesignMode.

When you load a Form at design-time, the constructor is called. You can
use the function that I gave you to do the check-and-move and you'd call it
from Sub New after the call to ComponentInitialize.

If you have any problems with it, show me how you are using the code and
we'll take it from there.

Regards,
Fergus
 
Jan,

In VS2003 you don't have to remove one control at a time. You can select
all controls (Ctrl-A) and all will move the same amount. This might even be
easier than writing code.

Regards,
Jan
 
Hi Jan
Thanks, I know that.
Basically I am an Access developer trying to migrate my skills to VB.Net.
The iterating is quite easy in Access and sometimes the task is quite more
complicated than just moving textboxes (which was my specific task this
time). Then it is nice to know how to do it in code.
So in this particular case your suggestion is easier, but I would like to
improve my VB.Net skills so doing things the easy way isn't always the right
thing for me.

Best regards

Jan
 
Hi Fergus
i feel quite stupid but I do not get it. I can't make the function
DoStuffToTheControls run without hitting F5. If I place a breakpoint in the
DoStuffToTheControls it is not activated when I open the project. Not until
I hit F5.


Here is the code for a sample form with 1 textbox
Public Class Form3

Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()

MyBase.New()

'This call is required by the Windows Form Designer.

InitializeComponent()

DoStuffToTheControls()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'Required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

Friend WithEvents TextBox1 As System.Windows.Forms.TextBox

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

Me.TextBox1 = New System.Windows.Forms.TextBox()

Me.SuspendLayout()

'

'TextBox1

'

Me.TextBox1.Location = New System.Drawing.Point(72, 120)

Me.TextBox1.Name = "TextBox1"

Me.TextBox1.TabIndex = 3

Me.TextBox1.Text = "TextBox1"

'

'Form3

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

Me.ClientSize = New System.Drawing.Size(448, 273)

Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.TextBox1})

Me.Name = "Form3"

Me.Text = "Form3"

Me.ResumeLayout(False)

End Sub

#End Region



Sub DoStuffToTheControls()

Dim oChildControl As Control

For Each oChildControl In Me.Controls

Dim pnt As Point

pnt.X = oChildControl.Location.X

pnt.Y = oChildControl.Location.Y - 75

oChildControl.Location = pnt

Next

End Sub

*********************
As you can see the textbox is drawn at location 72,120.
I still do not see how I can use the constructor without running the project
(that has Form3 as startup object).

I would like to create and call a function (in Access it would be completely
separated from the form itself) that permanently, once and for all changes
the location of the textbox to ie 72,50. So when I shut down Visual Studio
and reopens the project and look at the form in design view the textbox is
now drawn at location 72,50.


If this does not make sense I give up.

In Access I would open a Module and create the following function
Sub test()
DoCmd.OpenForm "tf", acDesign
Dim a As Control
For Each a In Forms("tf").Controls
If a.ControlType = acTextBox Then
a.Top = a.Top + 65
End If
Next
End Sub

Then I would run this function and bam!... The Form would change in
designmode.
(In Access a form always has a default instance, I know this is not the case
in VB.Net)

Thanks for your help

Jan
 
Hi Jan,

Sorry!! My apologies - I'm the stupid one. :-((

I've been playing with UserControls and working with DesignMode and it's
different with plain old Forms. And now I've found out why

When you open a Form up in Design Mode, VS doesn't call New, as I had
thought. What it does is go through ComponentInitialize, line by line, and
execute it as if it were actually being run. But it doesn't do anything that
it doesn't understand (which is why we're not supposed to make changes in that
routine). If it encounters anything there that it doesn't like it will
complain loudly.

So, my suggestion of putting DoSomethingToAllControls in New is a total
non-starter.

But !!

I also learned that if a designable class (Form, UC, etc) inherits from
another, then the constructor of <that> class <will> be called.

With
Public Class SomeForm
Inherits System.Windows.Forms.Form
the constructor of System.Windows.Forms.Form (SWFF) is called to do its
thing.


Now, consider
Public Class SomeForm_BASE
Inherits System.Windows.Forms.Form
and
Public Class SomeForm_ACTUAL
Inherits SomeForm_BASE
(where each is in a .vb file of its own)

When you show SomeForm_BASE in the Designer, you just get that Form and
the SWFF contructor. When you show SomeForm_ACTUAL, the constructor of
SomeForm_BASE is called and this can do what it likes. [As an aside, there
seems to be no way for the Base to know that it's being called on behalf of
Actual, but that may not be a problem.]


So how would this apply to your situation? Wekk, it may be more trouble
than it's worth but...

If you design your form in the usual way, SWFF constructor will be called.
Put anything in New and it won't run.
Public Class AUsefulFormWithControlsAndCodeAndEverything
Inherits System.Windows.Forms.Form
Public Sub New
MyBase.New()
InitializeComponent()
DoStuffToTheControlsOf (Me)
End Sub
: : :
: : :
End Class

VS ignores Public Sub New
It definitely calls MyBase.New but that's because of the Inherits.
It simulates a call to InitializeComponent().
There's no call to DoStuffToTheControlsOf.

But derive a new 'viewer' Form inheriting from the useful one, ie
Public Class SeeHowMyBaseLooksWhenItRuns
Inherits AUsefulFormWithControlsAndCodeAndEverything
'And no contents at all.
End Class

and DoStuffToTheControlsOf will be run. And not only New, it would seem,
but Load gets called as well - so be careful. DesignMode isn't applicable
inside the Constructor but it is within Load.


Once again, apologies for leading you astray (so confidently too, lol). If
this is of no direct use then I hope, at least, that it makes interesting
background information.

As always, any questions, give a shout. ;-)

Regards,
Fergus
 
Hi again Fergus
Thanks for your time and knowledge.

If I do as I think you suggest the inheriting form (not the base form) looks
like I want in design view.
Because "Me" refers to the inheriting form.
And I can't edit the properties of the controls on the inheriting form
directly (I can by editing the base form). So I'm basically stuck with an
extra form. And I can't edit the form that looks like I want it to.

Well...
You can't win 'em all.

This has taught me some things about VB.Net and I am very grateful for your
help. But I think I will stop now with this problem. (I (And you too I am
sure) have other problems to solve). They (ie my problems - not yours ;-) )
will appear in a newsgroup near you in the future unless I figure out how to
solve them myself.

Best regards

Jan





Fergus Cooney said:
Hi Jan,

Sorry!! My apologies - I'm the stupid one. :-((

I've been playing with UserControls and working with DesignMode and it's
different with plain old Forms. And now I've found out why

When you open a Form up in Design Mode, VS doesn't call New, as I had
thought. What it does is go through ComponentInitialize, line by line, and
execute it as if it were actually being run. But it doesn't do anything that
it doesn't understand (which is why we're not supposed to make changes in that
routine). If it encounters anything there that it doesn't like it will
complain loudly.

So, my suggestion of putting DoSomethingToAllControls in New is a total
non-starter.

But !!

I also learned that if a designable class (Form, UC, etc) inherits from
another, then the constructor of <that> class <will> be called.

With
Public Class SomeForm
Inherits System.Windows.Forms.Form
the constructor of System.Windows.Forms.Form (SWFF) is called to do its
thing.


Now, consider
Public Class SomeForm_BASE
Inherits System.Windows.Forms.Form
and
Public Class SomeForm_ACTUAL
Inherits SomeForm_BASE
(where each is in a .vb file of its own)

When you show SomeForm_BASE in the Designer, you just get that Form and
the SWFF contructor. When you show SomeForm_ACTUAL, the constructor of
SomeForm_BASE is called and this can do what it likes. [As an aside, there
seems to be no way for the Base to know that it's being called on behalf of
Actual, but that may not be a problem.]


So how would this apply to your situation? Wekk, it may be more trouble
than it's worth but...

If you design your form in the usual way, SWFF constructor will be called.
Put anything in New and it won't run.
Public Class AUsefulFormWithControlsAndCodeAndEverything
Inherits System.Windows.Forms.Form
Public Sub New
MyBase.New()
InitializeComponent()
DoStuffToTheControlsOf (Me)
End Sub
: : :
: : :
End Class

VS ignores Public Sub New
It definitely calls MyBase.New but that's because of the Inherits.
It simulates a call to InitializeComponent().
There's no call to DoStuffToTheControlsOf.

But derive a new 'viewer' Form inheriting from the useful one, ie
Public Class SeeHowMyBaseLooksWhenItRuns
Inherits AUsefulFormWithControlsAndCodeAndEverything
'And no contents at all.
End Class

and DoStuffToTheControlsOf will be run. And not only New, it would seem,
but Load gets called as well - so be careful. DesignMode isn't applicable
inside the Constructor but it is within Load.


Once again, apologies for leading you astray (so confidently too, lol). If
this is of no direct use then I hope, at least, that it makes interesting
background information.

As always, any questions, give a shout. ;-)

Regards,
Fergus
 
Hi Jan,

You're most welcome. It's taught me more too, and that's one of the things
I gain from being here.

|| You can't win 'em all.

Indeed not - we explore right up to the boundaries and then fall back on
the workaround. ;-)

Later Dude.

Regards,
Fergus
 
Back
Top