שתף באמצעות


How to declare variable to be used between forms

Question

Tuesday, February 24, 2015 2:59 PM

I have the following piece of code in Form2.  When I try to reference the strings in a Form3 subroutine, I get an error message saying the variables have not been declared.  Where (or how) do I need to declare these two variables to use them between forms?

Thanks,

Randy Boulter

All replies (25)

Tuesday, February 24, 2015 4:39 PM ✅Answered | 1 vote

Variables declared at form level for each of the forms are not recognized by the other forms.  You need to create a new module for declaring variables that will be recognized by all the forms in a project.  Click Project and select Add Module.  Declare the variable using the Public keyword.  However, you must very careful to use that variable correctly or you may incur errors that will be difficult to find and fix.  Remember to reset or reinitialize the variable as necessary.  Alternatively, you can refer to a variable declared as Public in one form, using the fully-qualified name which includes the name of the form.  

For example,

in Form2:  Public varname As String = "Hello"

in Form1:   MessageBox.Show(Form2.varname)

Solitaire


Tuesday, February 24, 2015 3:21 PM | 2 votes

Hi Randy,

Have you tried searching this forum for your question?  It has been answered many times...  the short answer is to pass references from Form2 to Form3, perhaps through properties defined on Form3, or by passing the entire Form2 instance to Form3.  You might also create a entirely separate class to store the common data values and then have both Form2 and Form3 utilize a reference to an instance of that class.  There's no one "right" answer as much depends on how much data and functionality is to be common to both forms.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Tuesday, February 24, 2015 3:39 PM

Forms are classes, and you should learn how to pass data between classes using an Interface.

http://www.dotnetperls.com/interface-vbnet


Tuesday, February 24, 2015 4:19 PM

You may want to update your post with the code. One option is to make the strings public properties of the Form so that they can be referenced as "Form2.PropertyName" from any other module.

Paul ~~~~ Microsoft MVP (Visual Basic)


Tuesday, February 24, 2015 5:11 PM | 2 votes

I would avoid getting into a situation where default form instances are being used as it can cause more issues than it resolves.  Better for a new developer to learn to pass instances correctly than to rely on VB-Only functionality that's questionable to begin with.

For completeness, here are some examples:

ASSIGN PROPERTY VALUES:

Public Class Form3
    Public Property SomeValueICareAbout As String
    Public Property SomeOtherValueINeed As Integer

    Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub
End Class

Public Class Form2

    Private form2StringVariable As String
    Private form2IntegerVariable As Integer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim otherForm As New Form3
        otherForm.SomeValueICareAbout = form2StringVariable
        otherForm.SomeOtherValueINeed = form2IntegerVariable
        otherForm.Show()
    End Sub
End Class

PASS FORM INSTANCE:

Public Class Form3
    Private sourceForm As Form2

    Public Sub New(source As Form2)
        InitializeComponent()
        sourceForm = source
    End Sub

    Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub
End Class

Public Class Form2

    Public form2StringVariable As String
    Public form2IntegerVariable As Integer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim otherForm As New Form3(Me)
        otherForm.Show()
    End Sub
End Class

PASS ENCAPSULATION CLASS INSTANCE:

Public Class StuffINeedWrapper
    Public Property StringVariable As String
    Public Property IntegerVariable As Integer
End Class

Public Class Form3
    Private localStuff As StuffINeedWrapper

    Public Sub New(stuff As StuffINeedWrapper)
        InitializeComponent()
        localStuff = stuff
    End Sub

    Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub
End Class

Public Class Form2
    Private localStuff As New StuffINeedWrapper

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        localStuff.IntegerVariable = 42
        localStuff.StringVariable = "test"
        Dim otherForm As New Form3(localStuff)
        otherForm.Show()
    End Sub
End Class

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Tuesday, February 24, 2015 6:07 PM

I'm still waiting to see if the OP can post his code. From his description there was no indication that anything was being "passed", and if the subroutine he is referring to in one Form is not being called or instantiated by the other Form then this isn't going to happen.

Paul ~~~~ Microsoft MVP (Visual Basic)


Tuesday, February 24, 2015 7:31 PM

Randy,

What I've come to do is somewhat of a combination of what's been mentioned here.

Usually though, I almost always need to pass in more than one thing and also I almost always have to pass back more than one thing (for example, letting the user modify something, then send back the "revised" version of it.

I've set up a simple example using all of the default names for the controls (Form1, Form2, Button1, etc.) and this way you can easily reproduce it. Form1 looks like this:

Given that I have to pass in and out multiple "things", I set up a class outside the class of Form1 - that gives it visibility anywhere in the project.

The code for Form1 follows:

Option Strict On
Option Explicit On
Option Infer Off

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) _
                           Handles MyBase.Load

        Button1.Enabled = False

    End Sub



    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
                                     ByVal e As System.EventArgs) _
                                     Handles TextBox1.TextChanged

        If TextBox1.Text.Trim <> "" Then
            Button1.Enabled = True
        Else
            Button1.Enabled = False
        End If

    End Sub



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

        Dim info As New InfoPassedBetweenForms(DateTimePicker1.Value, _
                                               CInt(NumericUpDown1.Value), _
                                               TextBox1.Text)

        Dim returnedInstance As InfoPassedBetweenForms = Nothing

        Using f2 As New Form2(info)
            f2.ShowDialog()

            If Not f2.userCancel Then
                returnedInstance = f2.returnValue
            End If
        End Using

        Stop

        ' Hover your mouse over "returnedInstance" above
        ' and you'll your revised information which has
        ' been passed back.

    End Sub
End Class





Public Class InfoPassedBetweenForms
    Private _dt As DateTime
    Private _number As Integer
    Private _text As String

    Public Sub New(ByVal dt As DateTime, _
                   ByVal num As Integer, _
                   ByVal text As String)

        Try
            If String.IsNullOrEmpty(text) OrElse text.Trim = "" Then
                Throw New ArgumentException("The text cannot be null or empty.")

            Else
                _dt = dt
                _number = num
                _text = text.Trim
            End If

        Catch ex As Exception
            Throw
        End Try

    End Sub

    Public ReadOnly Property DateTime() As DateTime
        Get
            Return _dt
        End Get
    End Property

    Public ReadOnly Property Number() As Integer
        Get
            Return _number
        End Get
    End Property

    Public ReadOnly Property Text() As String
        Get
            Return _text
        End Get
    End Property
End Class

Form2 has the same controls (in fact I literally copied/pasted them) and I have it set up that only if the text in the TextBox is non-blank AND is different than the instance passed in, then the button on Form2 will be enabled to allow them to then pass it back.

This is what it looks like running it:

The code for Form2 is shown below:

Option Strict On
Option Explicit On
Option Infer Off

Public Class Form2
    Private dataPassedIn As InfoPassedBetweenForms = Nothing

    Public returnValue As InfoPassedBetweenForms = Nothing
    Public userCancel As Boolean = True



    Public Sub New(ByVal info As InfoPassedBetweenForms)

        InitializeComponent()

        Try
            If info Is Nothing Then
                Throw New NullReferenceException("The information cannot be null.")

            Else
                dataPassedIn = info
            End If

        Catch ex As Exception
            Throw
        End Try

    End Sub



    Private Sub Form2_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) _
                           Handles MyBase.Load

        If dataPassedIn IsNot Nothing Then
            DateTimePicker1.Value = dataPassedIn.DateTime
            NumericUpDown1.Value = CDec(dataPassedIn.Number)
            TextBox1.Text = dataPassedIn.Text

            Button1.Enabled = False
        Else
            Close()
        End If

    End Sub



    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
                                     ByVal e As System.EventArgs) _
                                     Handles TextBox1.TextChanged

        If TextBox1.Text.Trim <> "" Then
            If TextBox1.Text.Trim = dataPassedIn.Text Then
                Button1.Enabled = False
            Else
                Button1.Enabled = True
            End If
        Else
            Button1.Enabled = False
        End If

    End Sub



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

        returnValue = _
            New InfoPassedBetweenForms(DateTimePicker1.Value, _
                                       CInt(NumericUpDown1.Value), _
                                       TextBox1.Text)

        userCancel = False
        Close()

    End Sub
End Class

I hope that gives you food for thought. :)

Still lost in code, just at a little higher level.

:-)


Tuesday, February 24, 2015 8:19 PM

Hello,

Take a look at the demo here, specifically button3 in the child form. Note the same can work in reverse also.

Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.


Tuesday, February 24, 2015 10:40 PM

In reading these threads, it amazes me to this day how developers don't know how to use an Interface to pass data between two forms/classes. :)


Tuesday, February 24, 2015 10:45 PM | 1 vote

In reading these threads, it amazes me to this day how developers don't know how to use an Interface to pass data between two forms/classes. :)

In your typical thrasonical manner, since you clearly know more than anyone here, pray tell - show us by example master Arnold.

Still lost in code, just at a little higher level.

:-)


Tuesday, February 24, 2015 10:52 PM | 1 vote

In reading these threads, it amazes me to this day how developers don't know how to use an Interface to pass data between two forms/classes. :)

In your typical thrasonical manner, since you clearly know more than anyone here, pray tell - show us by example master Arnold.

Still lost in code, just at a little higher level.

:-)

 Me as well Frank, I always thought that an Interface was to create an common entrance for classes. But not for passing data between two different classes.

:-)

In my opinion Reed describes in his first reply almost everything. Maybe he could have added that Visual Basic since version 2005 creates static form classes, but it is a way many like me don't like, so I always try to avoid to tell that.

Success
Cor


Tuesday, February 24, 2015 10:52 PM

___________________________________________________

Public Class Form2

    Public Str1 As String = "Something"

    Public Str2 As String = "Something else"

End Class

___________________________________________________

Public Class Form3

    Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        MessageBox.Show(Form2.Str1 & vbCrLf & Form2.Str2)

    End Sub

End Class

___________________________________________________

La vida loca


Tuesday, February 24, 2015 10:57 PM

 Me as well Frank, I always thought that an Interface was to create an common entrance for classes. But not for passing data between two different classes.

:-)

Success
Cor

Well, I've been experimenting with interfaces a bit lately and there's more to them than I realized. The fact that you can make an "is-a" comparison between two classes, based strictly on the fact that they each implement a given interface does open doors that I'd not thought of.

******

With that then, I really am interested to see how that will help in this situation. I learn lots here; perhaps this will be another. :)

Still lost in code, just at a little higher level.

:-)


Tuesday, February 24, 2015 11:30 PM

The MSDN VB forum rocks.  I've found more helpful people on this forum.  I went with Solitaire's answer, mainly because it was the simplest.  It is working now.  I forgot to post the code, but it just decalared two public strings in one form and then I tried to use them in another.  I was not passing anything. All the answers were helpful -  I'm learning!

Best regards,

Randy Boulter


Tuesday, February 24, 2015 11:33 PM

In your typical thrasonical manner, since you clearly know more than anyone here, pray tell - show us by example master Arnold.

Here it is dead in your faces. :) If you have done n-tier development, then you know about Interfaces and how powerful they are. If you have done Dependency Inversion Principle, IoC and Dependency Injection, then you know how powerful Interfaces are.

I got hip to Interfaces back in 2004, 2005 somewhere around there with MVP watch the shows, because Interfaces are  dead in your faces. And you can run for glory.

http://polymorphicpodcast.com/shows/mv-patterns

http://www.codeproject.com/Articles/465173/Dependency-Inversion-Principle-IoC-Container-Depen


Tuesday, February 24, 2015 11:48 PM | 1 vote

The MSDN VB forum rocks.  I've found more helpful people on this forum.  I went with Solitaire's answer, mainly because it was the simplest.  It is working now.  I forgot to post the code, but it just decalared two public strings in one form and then I tried to use them in another.  I was not passing anything. All the answers were helpful -  I'm learning!

Best regards,

Randy Boulter

Good to hear your issue has been resolved but keep in mind the simple solution is not always the wise solution, no different than using a overly complex solution.

Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.


Wednesday, February 25, 2015 12:32 AM

I went with Solitaire's answer, mainly because it was the simplest.  It is working now.  I forgot to post the code, but it just decalared two public strings in one form and then I tried to use them in another.

Which one are you using?   If it's the equivalent of

         MessageBox.Show(Form2.varname)

then you are probably relying on the default instance of form 2, which will eventually create a problem that might be very difficult to track back to this code.


Wednesday, February 25, 2015 1:08 AM

The MSDN VB forum rocks.  I've found more helpful people on this forum.  I went with Solitaire's answer, mainly because it was the simplest.  It is working now.  I forgot to post the code, but it just decalared two public strings in one form and then I tried to use them in another.  I was not passing anything. All the answers were helpful -  I'm learning!

Best regards,

Randy Boulter

Hey, that was my suggestion. No fair! ;-)

Paul ~~~~ Microsoft MVP (Visual Basic)


Wednesday, February 25, 2015 2:11 AM

In your typical thrasonical manner, since you clearly know more than anyone here, pray tell - show us by example master Arnold.

Here it is dead in your faces. :) If you have done n-tier development, then you know about Interfaces and how powerful they are. If you have done Dependency Inversion Principle, IoC and Dependency Injection, then you know how powerful Interfaces are.

I got hip to Interfaces back in 2004, 2005 somewhere around there with MVP watch the shows, because Interfaces are  dead in your faces. And you can run for glory.

http://polymorphicpodcast.com/shows/mv-patterns

http://www.codeproject.com/Articles/465173/Dependency-Inversion-Principle-IoC-Container-Depen

Thanks for the links - I'll look at those sometime, but as I thought, you didn't post an example using your own code.

That bespeaks volumes about your character.

Still lost in code, just at a little higher level.

:-)


Wednesday, February 25, 2015 5:08 AM | 1 vote

In reading these threads, it amazes me to this day how developers don't know how to use an Interface to pass data between two forms/classes. :)

In this case it would be like eating soup with a shovel... this situation does not call for such a large tool.

Sure, interfaces can be used to define code contracts between objects to ensure a consistent usage pattern.  Part of this contract can involve the methodology for sharing data between objects.  Its all good and well when it serves a purpose.

But an interface does not implicitly provide the ability to pass data between objects and it doesn't make sense to define an interface if there will only be a single encapsulation class to implement it.  So while an interface could be involved in a complex solution to the question in this thread, it is by no means a solution in and of itself.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Wednesday, February 25, 2015 5:17 AM

In my opinion Reed describes in his first reply almost everything. Maybe he could have added that Visual Basic since version 2005 creates static form classes, but it is a way many like me don't like, so I always try to avoid to tell that.

Success
Cor

Yup.  I avoided it on purpose and only added a second post after it was mentioned.

Both default form instances as well as modules created for no other reason than to make objects available to other objects are anti-patterns in OOP and should be avoided.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Wednesday, February 25, 2015 7:00 AM

** So while an interface could be involved in a complex solution to the question in this thread, it is by no means a solution in and of itself.**

I don't teach what can be done.   I teach would could be done if one puts his or her mind to it. If one wants to be an effective .NET developer creating .NET solutions from the front-end to the back-end not just at the fly-boy UI and the lipstick on that pig, then one had better know how to use Interfaces to allow classes/objects  to communicate with each other - period and point-blank. 

Sure one can do the Mickey Mouse if that' what one is interested in, but most developers want to do better and most want to see other than the Mickey Mouse.


Wednesday, February 25, 2015 8:59 AM

I got some of this around in VB somewhere. This is one out of 3 forms in a n-tier windows demo solution all sharing the same Service Layer,  WCF, BLL and DAL. It's Interfaces being used in all the objects from the UI to DAL using MVP.

The Interface

using BLL.DTO;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DemoWindowsFormApp.Views
{
    public interface IArticleView :IView
    {
        int Idx { get; set; }
        List<DTOArticle> DtoArticles { get; set; }
        Label LblArticleId { get; set; }
        TextBox TbxTitle { get; set; }
        TextBox TbxBody { get; set; }
    }
}

The form class

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using BLL.DTO;
using DemoWindowsFormApp.Presenters;
using DemoWindowsFormApp.Views;
using Services;

namespace DemoWindowsFormApp
{
    public partial class ArticleView : Form, IArticleView
    {
        #region Members
        private ArticleViewPresenter mPresenter;
        #endregion

     

First of all is this OT code in this forum, it is not VB but C#.

However, most of all it is not passing data between two forms. 

It describes one form which has a contract (Interface) that there must be on that form 5 properties:

An index, A generic List, a Label, and two textboxes. 

That is not the way for what an Interface was originally meant. This is a good example how to use a shovel to drink coffee. (Free quoting Reed).

In some (describing) development tools the interface is used to get a high abstraction. But then it is nothing else than a replacement for the C++ header.  And yes, they created Java which was as easy as drinking coffee to avoid the headers. C# and in fact Visual basic have inherited that from Java.

Success
Cor


Wednesday, February 25, 2015 1:30 PM

First of all is this OT code in this forum, it is not VB but C#.

Any coding monkey can write and read code. It's not about that. It's about design patterns and how to use interfaces between classes to pass objects or data between classes. Learn how to design solutions and not just bang out code for the sake of banging out coed.

**However, most of all it is not passing data between two forms. **

It's about passing objects or variables between classes. After all, a Windows form is class/object. an the principles of using an interface on a class applies.

https://msdn.microsoft.com/en-us/library/system.windows.forms.form%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

That is not the way for what an Interface was originally meant. This is a good example how to use a shovel to drink coffee. (Free quoting Reed).

You both are flat out wrong, and your minds are closed on separation of duties and using UI design patterns like MVC, MVP, MVVM and MVPVM.

In some (describing) development tools the interface is used to get a high abstraction. But then it is nothing else than a replacement for the C++ header.  And yes, they created Java which was as easy as drinking coffee to avoid the headers. C# and in fact Visual basic have inherited that from Java.

They didn't inherit anything from Java. OO is OO and the principles are the same between .NET and Java the two OO language platforms.

You disappoint me here Cor.


Wednesday, February 25, 2015 1:51 PM | 1 vote

Greetings all,

There are good points made and healthy discussing but let's not lose sight that the OP is fairly new to the game and like many is looking for a simple solution rather than getting into what many of us call normal when used appropriately while for others they could careless and rightfully so, they must crawl before they walk and walk before they run.

If you push someone to hard in a direction that they are not comfortable with they will not want to hear it be it right or wrong.

Let's keep the learning experience just that, a learning experience that allows those asking questions to feel comfortable. Of course for someone asking a question that should know better it's alright under the proper conditions to push them gently onto the straight and narrow path.

Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.