Passing variables and controls using WinForms and VB.NET

Bucky

Contributor
Joined
Dec 23, 2001
Messages
791
Location
East Coast
Having seen multiple questions regarding showing forms and
passing variable, I thought it'd be necesarry to explain the
differences of using Forms in VB6 and VB.NET. This'll also take a
little work off people having to explain this idea more than once.

Please feel free to leave any comments and suggestions. I'd
like to know if the tutorial is too wordy, and if I should
shorten it.

-------

Forms in VB.NET

This short and simple tutorial is long overdue, and hopefully it will clear up confusion regarding the use of forms in VB.NET, compared to their use in VB6. This tutorial assumes the reader's knowledge of basic VB.NET syntax and the basics of object-oriented programming.

This tutorial is intended to answer such questions as:
  • Why can't I show (name of form) just by using (name of form).Show()?
  • How can my form access variables that are in other places?
  • What is the answer to Life, the Universe, and Everything?
Visual Basic 6 handled (note the use of the past-tense) forms in a secretive, almost mysterious way. Forms were this magical entity that could be shown and hidden at a moment's notice. They had some qualities of classes, but they still hid a lot of functionality from the user.

The coder transferring from VB6 to VB.NET must think of forms in an entirely new way. A Form in VB.NET (and indeed, the entire .NET Framework) is now a standard class module. A Form acts as any other class does: a new instance of the Form class is initialized, the instance is manipulated and used, and then it is disposed of. This is very important to understanding that everything you know about forms in VB6 is wrong. ;)

Working With Forms

That being said, here is a short example of a Form (Form1) opening another Form (Form2) upon the click of a button (Button1).
Visual Basic:
Public Class Form1
  Inherits System.Windows.Forms.Form

  ' Windows Forms Designer generated code region

  Private otherForm As New Form2()

  Private Sub Button1_Click(ByVal sender As System.Object, _ 
    ByVal e As System.EventArgs) Handles Button1.Click

    otherForm.Text = "Foo"
    otherForm.Show()
  End Sub

End Class

Here's where the difference of showing forms comes into play. In the General Declarations area of Form1, I declared a new instance of the Form2 class. The local variable otherForm is accessible to any subroutines inside the Form1 class. The Text property of the form was changed to show how other members of otherForm can be accessed.

Passing Values Between Forms

If forms are so disconnected, how are values passed between them? You can't just get the value of Form1.VariableName from Form2, because that's how VB6 did it, and thus VB.NET does it differently. If you can get into this state of mind, then you will pick up the changes in VB.NET quickly. :)

Now, I bet you're wondering, why not just create some public variables in a module and call it a day? Like what was just mentioned, this is how VB6 does things, and thus it is wrong. Modules should be considered obsolete, because they go against the OOP paradigm. If you want to create members accessible to your entire project, create them as static (Shared in VB.NET) members of a class. Here, however, it makes more sense to pass the values to the Form's constructor.

Because Forms are classes, you are free, as an inheritor of the class, to override or overload its constructor. Using this technique, you can overload the constructor of a Form to accept variables being passed to it.

Take the Form1/Form2 example again. Here, the code for both Form1 and Form2 is shown.
Visual Basic:
Public Class Form1
  Inherits System.Windows.Forms.Form

  ' Windows Forms Designer generated code region

  Private otherForm As New Form2("Foo")

  Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    otherForm.Show()
  End Sub
End Class

' ----------------------

Public Class Form2
  Inherits System.Windows.Forms.Form

  ' Windows Forms Designer generated code region

  Private param As String

  Public Sub New(ByVal newParameter As String)
    MyBase.New()
    InitializeComponent()

    param = newParameter
  End Sub

  Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    MessageBox.Show(param)
  End Sub
End Class

The only change in Form1 is that the declaration of Form2 passes the string "Foo" to its constructor. In Form2's code, the constructor has been overloaded (the original Sub New is inside the Windows Forms Designer code region) to accept a string and set it to a local variable. Then, when Button1 is clicked on Form2, the variable is displayed to the user. Any type and number of variables can be passed to constructors, including other Form instances (if, for example, you wanted to refer back to Form1 from Form2).

It's important to note that the first two lines of the overloaded constructor are required in any constructor, for they make sure that the form and all its control initialize properly. The InitializeComponent sub is, not surprisingly, also in the code region.


Let's say that you wanted to be able to access all the members of Form1 from Form2. Instead of passing a string the constructor, like in the example, you would pass a parameter of the Form (or Form1) type instead.

Here's the revised code. Form2 now shows the contents of TextBox1 on Form1 to the user when the button is clicked. Note how Form1 passes itself (Me) to the constructor of Form2, and that Form2's constructor now accepts a variable of type Form1.
Visual Basic:
Public Class Form1
  Inherits System.Windows.Forms.Form

  ' Windows Forms Designer generated code region

  Private otherForm As New Form2(Me)

  Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    otherForm.Show()
  End Sub
End Class

' ----------------------

Public Class Form2
  Inherits System.Windows.Forms.Form

  ' Windows Forms Designer generated code region

  Private callingForm As Form1

  Public Sub New(ByVal newCallingForm As Form1)
    MyBase.New()
    InitializeComponent()

    callingForm = newCallingForm
  End Sub

  Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    MessageBox.Show(callingForm.TextBox1.Text)
  End Sub
End Class

Summary

When working with forms, remember that:
  • Forms are merely classes that can be manipulated in any way a class can.
  • To pass values to a Form (including another Form), overload the constructor of the Form to accept these values.
  • If you try to do something in VB.NET using a VB6 technique, chances are it won't work and/or it's bad coding practice. Find a new way.
  • The answer is 42.

Feel free to PM me with any questions or comments.
Happy coding!
 
Last edited by a moderator:
Back
Top