Click here to Skip to main content
15,890,825 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
After 47 years as an IT consultant and written code in a number of programming languages I retired 5 years ago and to keep my brain active I converted a program I originally wrote in dBaseIII (yes I am ancient) and migrated through Foxpro into Visual Foxpro (which all are no longer supported by Microsoft) into Visual Basic. I found Visual C# was one step to far for me as my main recent experience was designing large to very large Microsoft Exchange solutions.

I got my programming going but it was rooted into historical forms design. So I decided to have a go at using menus instead. I have the basic redesign going but I need to create a multiple of sub forms programtically otherwise I am going to have a vast number of forms being designed when they are simple enough to be programatically be created and destroyed as required.

My issue concerns accessing the controls I have created on the programatically created form and the events triggered for that form. This is a precis of what I have designed and coded so far:

For my parent form at the Public Class level I declared
Dim frmAuthorEdit As New System.Windows.Forms.Form

I have then placed a databound datagrid on the parent form. When I right click on a grid entry on this form, I enter a sub called gridname.CellMouseDown. Within this sub I create a new form programatically thus
frmAuthorEdit = New Form

and I added an event handler to it like this
AddHandler frmAuthorEdit.Load, AddressOf frmAuthorEdit_Load

I then show the form.

Still within this same parent class I have declared a sub like this
Private Sub frmAuthorEdit_Load(sender As System.Object, e As System.EventArgs)

Within this sub frmAuthorEdit_Load I programatically add to this new form numerous labels, textboxes and command buttons. For example for a new textbox I did
Dim txtDisplayName = New TextBox

and I added an event handler to it thus
AddHandler txtDisplayName.TextChanged, AddressOf txtDisplayName_TextChanged

This all works OK.

Within the sub txtDisplayName_TextChanged I want to be able to access all of the textboxes I have created in the frmAuthorEdit_Load sub when I change information on the frmAuthorEdit form.

As a totally self taught programmer (to aid me with customer projects) object orientated languages are a challenge to me so I apologise for my ignorance in advance in what could be a simple answer.

What I have tried:

VB2019


I have tried changing the declaration Dim frmAuthorEdit As New System.Windows.Forms.Form from the top class level to the frmAuthorEdit_Load sub but neither of these actions solved my problem.

In the sub
Private Sub txtDisplayName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)

via sender I can extract the text from the textbox selected but my issue is how do I then update other textboxes on this form with the revised text that has changed from the first textbox that kicked off the event?

I have tried everything I can think off and can find under Google but so far I have totally failed. Things I have tried include
frmAuthorEdit.txtDisplayName.text = "New text"

This fails with txtDisplayName is not a member of 'Form'

If I change the command to
me.txtDisplayName.text = "New text"

This fails with txtDisplayName is not a member of 'MyStartFromName' - as I would expect as this control is not on that form.

So how do I access the controls on this programatically created form?
Posted
Updated 5-Apr-21 3:25am

1 solution

If you create them dynamically, then you can't refer to them by name as part of your form - they would each need a separate form level variable for that to work.

But ... assuming that you added each dynamic control to your Form.Controls collection (or a subcontainer) so they are displayed, then you can traverse the relevant collection and find all the controls you added.
And to locate the one that caused the TextChanged event to be raised (he one the user edited) is simple: it's passed to the event handler as the sender parameter.
So all you need to do is cast sender to a TextBox, get the Text from that, and loop though the Controls collection updating all the other controls (remembering to skip the original one).

The only other problem you will have is that each time you update another text box, it will raise it's own TextChanged event - which will not be handled until you exit from the original one, so you will need to skip those events as well. One way to do that is to set the Control.Tag property to indicate that the event should be ignored and just clear it when the event fires - again, the sender property will contain the actual control.
 
Share this answer
 
Comments
Derek Carpenter 2021 7-Apr-21 14:36pm    
Thanks for the prompt reply and I am sorry for my ignorance. Could you provide me some sample VB code to do this please? As I said in my introduction I am a self taught programmer and I don't understand the comment cast Send to a textbox.
My code picks up the sender value no problem. My issue id wrting that sender value back to me textbox control.
OriginalGriff 7-Apr-21 15:29pm    
"sender" is declared as an "object":

Private Sub frmAuthorEdit_Load(sender As System.Object, e As System.EventArgs)


Because all event handlers do.
What it contains is the source control that generated the event: for a Button click, it would be the Button the user tapped on; for a Form Load, it would be the instance of the Form. For a TextChanged event, it's the TextBox the user typed in.
So to use it, you have to cast the object back to the source type: a Button, A Form, a Textbox:
    Dim tb As TextBox = TryCast(sender, Textbox)

    If tb IsNot Nothing Then
        Console.WriteLine(tb.Text)
    End If
Make sense now?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900