# VBForums CodeBank > CodeBank - Visual Basic .NET >  The Definitive "Passing Data Between Forms"

## Shaggy Hiker

After seeing so many of these types of questions, I thought that coming up with one definitive answer was a good idea. Kleinma seemed to agree, so I started rooting around in the database looking at the patterns that this type of question took, and I came up with three general forms of the question. I don't know whether I have enough information to create an ultimate answer, so I thought I would put out what I have found so far, and ask people for comments and inputs:

1) How do I transfer data between Form1 and Form2.

This is actually not that common a question, which is probably because the answer is straightforward. There are three types of general answers. 

a)The first type would be to add public member variables to either Form1 or Form2. In either case, any code that sees either Form1 or Form2 can read the variables directly. I'll say no more about this answer, because it is quick, but not a good habit to get into.

b)A better solution would be to add PRIVATE member variables to one of the forms, and make them accessible through properties:


vb Code:
Public Class Form1
  
   Private myInteger as integer
    Public Property myInt(value as integer) as integer
     Get
       Return myInteger
     End Get
     Set
       myInteger = Value
     End Set
   End Property
End Class

This solution adds a bit more code than just making the variables Public, and there is no advantage to this technique in the above example. However, by using a property, you have some control over what is getting passed in, and how it is being dealt with. A form is a class, and a class should be the sole owner and gaurdian of its data. The class itself should control what data is accessible, and how. By using properties, you can make members ReadOnly, WriteOnly, or open to all. You can also make the protected, which affects inheritance. Furthermore, you can use the Set block to restrict input values, and can use the Get block to resolve requests for things that are otherwise improper (like asking for item 10 in a 9 element array).

In general, you can put the property on Form1 and have Form2 go get it, or put the property on Form2 and have Form1 push the data to Form2. Which you choose depends entirely on what makes sense. If Form2 is created by Form1, then it makes sense for Form1 to fill Form2 simply because Form1 is "creating" Form2. If Form2 is independent of Form1, then it makes sense that Form2, when it is created, goes and gets the data it needs from Form1.

c) An alternative, if Form2 is being created by Form1 is to overload the constructor (the Sub New for the form) to either accept arguments that have the data, or to go get the data from the properties of other classes, as needed. The advantage of this technique is that it is a very clean way to create the form, and can be used to FORCE the correct initialiaztion of the form. If you overload the constructor with arguments, you could change the default constructor to Private, such that the overloaded constructor is the ONLY way to create the form. By doing this, you enforce the requirement (even on yourself) that the form be called with the correct arguments. Since these arguments can be the data pieces needed by the form, this will enforce the correctness of the form. 

If you use the default instance of a form, then you can't use the overloaded constructor technique to move data to a new form. The reason for this is that the default instance uses a default constructor which takes no arguments. Therefore, if you are using the default instance, use properties.

Having said all that, I should repeat that this form of the data transfer question is relatively rare. MUCH more common is this:

2) I want to move data from Form1 to Form2, but when I do, the data isn't there, even though I can see it. What is wrong?

This isn't actually a data transfer issue at all, but a fundamental misunderstanding about variables. I suspect that this problem is worse for people coming from VB6 to .NET, and for users of 2005 rather than 2003, because of the default instances in both VB6 and 2005.

When a variable is declared:

Dim myForm as Form1.

That line instructs the compiler to set aside sufficient memory for an object of type Form1. No actual form is created, and the memory, if you could see it, would be nothing but garbage. You create the form when you write the word New:

myForm = New Form1

This tells the compiler to create a new instance of the object called Form1, and put this object in the memory called myForm, which was previously set to the size needed to hold a Form1. It is the New statement that fills the garbage memory with an actual, orderly, instance of Form1.

The problem that people seem to be having when they ask this form of the question is that they are creating a new instance of Form1, and expecting that it will have the data that is already found in an existing instance. However, the Dim statement is telling the compiler to set aside a totally new chunk of memory, and the New statement is telling the compiler to create an entirely new instance of the object. Naturally, a totally new instance is not the same as any existing instance, so when you look at the properties of this totally new instance, they will not contain the data that was added to an existing instance. Worse, if you don't actually use New, you won't have an actual object, but just some garbage chunk of memory of the right size for the object, but not an actual object.

The solution in this case is to use the existing instance and not create a new instance. I have not come up with any general means to do this, as it depends entirely on the specific design. A few options are these:

 a) If the other instance was created at some other, earlier, time, then there will be a line like oldInstance = New Form1. Thus, oldInstance is the instance that holds the data you want, so don't create a new instance like dim f1 as New Form1, but use oldInstance instead. This may not be easy, because the existing program design might well have oldInstance delared in such a way that it is inaccessible to another form (it might be a private member variable, or it might be declared with function scope rather than class scope). The only way to fix this would be through changing the design so that the oldInstance is accessible, or by a fairly hideous workaround of putting the data from oldInstance into a different class that is visible to the instance of Form2, and getting the data from that intermediate class.

b) If Form2 is being created from Form1 (e.g. a button click event creates the instance of Form2), then just add a property to Form2, and have Form1 populate it as described for the first form of the question, rather than having Form2 try to go and get the data from Form1 once it has been created.

3)Passing data from Parent form to Child form in an MDI environment?

This form of the question is pretty common, but takes many forms, as people seem to have different ideas of what is the parent and what is the child. Furthermore, I don't see any particular pattern to these questions, nor the answers to them. Also, I have no experience with MDI environments. Therefore, I need somebody else's input as to whether there is some comprehensive answer to this type of the question.

Ok, there's my first pass, with minimal editing. I'd like some edits, suggestions, and etc.

----------


## Mr.No

Quite some interesting bits here. When I need to pass data to and from forms I usually use a class object to hold all properties I need and have the forms exchange just one object instead of lots of properties.

Secondly if I need to have a single instance of a form then I use the Singleton pattern where i use something like Factory.CreateForm() to ensure that only one instance of the forms exists across the application.

----------


## warrenayen

I prefer to use a class object, as well, where I can access any of it's information from any form, rather than having to remember the specific form the variables are part of.

For instance, all of my projects here at work contain a common class that is called by the Application name (such as UnifiedClass). Many of them contain similar variables and properties and enums and methods that I can use over and over again in each project with almost no modification. To do the same with forms would require me to import those forms, remove the code, add that code to the new forms, and then exclude those imported forms - far more work.

----------


## warrenayen

Also, for MDI environments, the child form can use the:


vb Code:
Me.Parent

This allows the child form to access the properties, controls, methods, and events of the parent form.

----------


## Shaggy Hiker

Both good points, though the second one is somewhat irrelevant to passing data.

However, I was considering this morning whether or not it is ever really justified to move data from a form to a class not in the form. I do have a program where the vast majority of the data does not reside in a form, but is held in a class external to all forms. The forms simply display data from the class. Of course, this is a special case, but the class could have been implemented as a member of one of the forms, though it would have had to be implemented as a shared member.

Therefore, it appears that in some designs, it would make some sense for forms to pass data to an intermediate class from which all forms could draw, though as far as I can see, this is NEVER necessary.

----------


## Shaggy Hiker

> I prefer to use a class object, as well, where I can access any of it's information from any form, rather than having to remember the specific form the variables are part of.
> 
> For instance, all of my projects here at work contain a common class that is called by the Application name (such as UnifiedClass). Many of them contain similar variables and properties and enums and methods that I can use over and over again in each project with almost no modification. To do the same with forms would require me to import those forms, remove the code, add that code to the new forms, and then exclude those imported forms - far more work.


Congratulations, you have realized the promise of OO design. The major reason it was created was code re-use. This often happens when you make several similar programs, especially ones dealing with the same core set of data. Great efficiencies can arise.

Oddly, I was writing about an intermediate class as this showed up, or else I simply overlooked it the first time.

----------


## warrenayen

It depends on the project:

For instance, in the Inventory Control module of Unified, when you select an Item, you can, from that form, view 5 other forms that need that particular item's #. I can either put that in the UnifiedClass (and all 5 forms can just say "unified.whatever"), or I can pass it to variables on each of those forms. 

It's a matter of preference, in the end, but it feels quicker and more efficent to assign it once to the class than to store it locally on the form or to access it from a previous form...sometimes certain information is accessed by all parts of the program (such as who is logged in and what console ID, for auditing purposes).

----------


## warrenayen

Yes, you're right - I was kinda overshadowing what you're referring to - simply passing a value from one form to another. I just thought if we make sure newer users move directly to OO, even for small tasks, they can quickly realize how much more efficent it is when it comes to harder stuff.  :Smilie:

----------


## Shaggy Hiker

> Also, for MDI environments, the child form can use the:
> 
> 
> vb Code:
> Me.Parent
> 
> This allows the child form to access the properties, controls, methods, and events of the parent form.


I think this is why that third category seemed so nebulous. Since there is a standard way to access the parent, the questions that remain tend to arise from other misconceptions rather than simply passing data from form to form, and these misconceptions don't fall into any recognizeable category. Therefore, I think that MDI questions are distinctly different from SDI questions.

----------


## warrenayen

Eh, it depends on the parent, too - I'm using a container parent for all forms in Unified. That way everything has a similar look and feel (unified design). Whenever I want to access a control on the main container form (which is what I prefer to call MDI parents), I simply say Me.Parent.pnHeader (the header bar), and change it however I want. Or use anything on the form  :Smilie: 

However, this doesn't work for things like Panel controls and so on - they rely on the common set. I can't do things like "me.control.item(0).parent.checked = true" because it's not common to that object...that makes some things difficult, or I haven't figured out yet how to do it  :Smilie:

----------


## kleinma

in addition to passing data between forms via a public property exposed on the form, if a form needs data from another form and it ALWAYS Needs said data when it is to be shown, I will often overload the forms New constructor to pass the param in right when I create the form. This is nice because lots of times you will write code like



```
Dim MyForm as New Form1
MyForm.SomeProperty = True 'BETTER NOT FORGET TO SET THIS
MyForm.ShowDialog
```

Or if you change the forms Sub New to accept a boolean, you could just do


```
Dim MyForm as New Form1(True)
MyForm.ShowDialog
```

----------


## bgmacaw

> Or if you change the forms Sub New to accept a boolean, you could just do
> 
> 
> ```
> Dim MyForm as New Form1(True)
> MyForm.ShowDialog
> ```


I think one of the most overlooked techniques in VB.NET form management is that the New method of a form can be overloaded as you've shown here. Many programmers, particularly those coming from VB6 since it didn't offer parameters on constructor methods, tend to overlook this option.

One example of how I used this recently was with a MDI app that had a report selection sidebar (reports for a specific date or patient could be selected). The selected report criteria would be passed to the overloaded New method of a MDI child form and the form would use this information to populate itself.

----------


## kleinma

I agree.

Not only did VB6 not have overloaded constructors, it didn't have them at all.

If you made your own class, you could declare it using the New keyword, but there was no actual New routine in the class, it was just basically a keyword that told the runtime to create a class instance.

.NET rocks!

----------


## steve_rm

Hello,

Just recently I have always used a global collection of my variables in a class, and using the public properties to get and set them. 
i.e. as i have my code open.


vb Code:
Private Shared customerSoftwarePart As Integer
  'Get and set the customers's software
    Public Property customerSoftwarePartID() As Integer
        Get
            Return customerSoftwarePart
        End Get
        Set(ByVal value As Integer)
            customerSoftwarePart = value
        End Set
    End Property

I have also used the constructor to pass data on to the form as well. 

I guess its just personal and consistency on the programmer to decide which one is best.

Steve

----------


## kleinma

why would you declare the customerSoftwarePart variable as shared, when the property exposing it is not shared?

----------


## Shaggy Hiker

Besides which, a module is a Public Shared class, so you might as well just use a module.

----------


## techgnome

> Eh, it depends on the parent, too - I'm using a container parent for all forms in Unified. That way everything has a similar look and feel (unified design). Whenever I want to access a control on the main container form (which is what I prefer to call MDI parents), I simply say Me.Parent.pnHeader (the header bar), and change it however I want. Or use anything on the form 
> 
> However, this doesn't work for things like Panel controls and so on - they rely on the common set. I can't do things like "me.control.item(0).parent.checked = true" because it's not common to that object...that makes some things difficult, or I haven't figured out yet how to do it


Ick... I cringe when I see that.... I prefer to expose events, raising them from the child form. Then I can let the parent form decide if it's going to deal with the event or not. I had a situation where all my child forms inherited from a main form (for consistency, gawd I love OOP) and they all raise status events for some of the actions going on. In a couple of cases, I don't care to know what a particular form is doing, so I extended the EventArgs parameter to include a key name that allows me to identify who raised the event. Then from there, the parent can decide to deal with the message, or ignore it.

I also used this same technique to send messages from one form to another via the parent. Child 1 raises the messageQueued event, the Parent traps for it, sees that it's for another Child (Child 2)... makes sure we have an instance of Child 2, and passes the message on. If no instance of Child is found, the message is tossed.

-tg

----------


## daemonk

one issue that was always kinda fuzzy to me but I never bothered to find out why because it just worked was:

-I have a form, TempForm with a public member, TempDS as dataset.
-I declare this TempForm.TempDS = AnotherForm.Dataset. 

when I make changes to TempDS in TempForm, the DataSet in AnotherForm also gets changed. 

I always thought the value of DataSet in AnotherForm was being copied to TempDS in TempForm. So when you change TempDS inTempForm, DataSet in AnotherForm will not get changed. But it seems the reference to DataSet in AnotherForm was passed instead. 

When I do the same thing with like a string or int type public member, the value gets copied, the reference doesn't get passed. Do VB.net pass reference or value differently based on what variable you use?

----------


## Shaggy Hiker

Actually, this is the behavior for all reference types. Watch carefully, and you will find that it happens for strings as well. What is happening is that a reference type is nothing but a pointer (the address of the first byte of the object). When you copy a reference type, you copy only the address. This is called a shallow copy. For it to behave otherwise would be called a deep copy, and you have to implement that yourself for all objects that don't already have a Copy method (string does).

The reason for this is that an object can hold pointers to other items, such as arrays of objects, other strings, etc. Simply creating a new instance of the object leaves some ambiguity: Do you make copies of all the underlying objects? And if so, how? Some objects require very specific actions to create, so would you call the constructors for them? Do you have all the data needed to call their constructors?

C++ has something called a copy constructor that allows for a deep copy. The copy constructor doesn't actually do anything, though, all it is is a standardized method signature, you are still required to explicitly code how this copy is supposed to happen. .NET has no standardized form of a copy constructor, but you still have to code how this happens.

If you want a deep copy, that is, you want to make a true copy of an object, you have to create a method to do so. Without that, you are just copying the address to the first byte of memory for the object, and nothing more.

----------


## Shaggy Hiker

I have now edited the original post to include a paragraph on the use of an overloaded constructor. I think I captured what could be done with that, but have a look.

----------


## daemonk

Whenever I passed strings or ints, the value always gets copied over instead of reference getting passed. Does it have to do with the "new" syntax? 

In my example with the public member TempDS as dataset, it isn't declared as a "new" dataset, so the reference is passed?

When you declare public TempString as String, a new string is created and the value of that string is equal to whatever value you give to it. So the value is passed instead of the reference?

----------


## kleinma

> Whenever I passed strings or ints, the value always gets copied over instead of reference getting passed. Does it have to do with the "new" syntax? 
> 
> In my example with the public member TempDS as dataset, it isn't declared as a "new" dataset, so the reference is passed?
> 
> When you declare public TempString as String, a new string is created and the value of that string is equal to whatever value you give to it. So the value is passed instead of the reference?


The difference you are noticing has to do with value and reference types. It doesn't have to do with the New syntax so much as it has to do with ByVal or ByRef when you pass a parameter. The default is ByVal, and generally this simply gets inserted in for you by the IDE while you are coding, You almost NEVER have to type it yourself. Usually if anything, its changing a ByVal to ByRef manually.

Value types can be passed ByVal or ByRef, and will act accordingly. Passing one ByRef means the changes you make in the routine you pass it to will persist back to the one you called it from. ByVal makes the copy when it sends the value into the routine you call.

Reference types are the opposite, because passing a reference type ByVal or ByRef is actually just passing the pointer in memory ByVal or ByRef to the calling routine. The pointer itself will still be pointing to the same place in memory, so the value(s) of the object passed can be manipulated in a called routine, and they will persist back to the main routine when the called one finishes.

----------


## Shaggy Hiker

A string was a reference type in 2003, and did not act like an integer. I haven't looked in 2005, but I assumed it was the same thing.

The behavior you are seeing for strings is not what should be happening. Strings should act the same as the dataset, not the same as an integer. Are you sure you have actually seen this for strings? You would have to do a bit of testing, but this should not be happening.

In pretty nearly all languages, a string is nothing but the address of the first character in the string (this isn't quite true, but it is true enough, so don't lets have those technical folks jump on me for being a bit casual). The string starts at that byte, and continues on until it reaches a termination character. Thus the size of the string variable is the size of a four byte memory address, regardless of the length of the actual string. If what you are saying were true, then when you assigned one string to another:

string1 = string2

Then the equal sign would have to dereference string2, figure out the length of string2, allocate sufficient memory to hold a string of that length, copy each byte of string2 into that new memory, and put the address of the first byte of that new memory in string1. To put it simply: It ain't very likely!!

What it is actually doing is just copying the four byte memory address that is held in string2 into string1, and that's all (except for incrementing a reference in the smart pointer, but we'll ignore that). This means that string1 and string2 both hold an address to the exact same chunk of memory. When you change string2, you change string1, and vice versa, because they are the exact same thing. Only if you use the String.Copy method will you get a second chunk of memory, with distinct addresses being held in each.

For .NET to work in any other way would require the = operator to act differently for strings than it does for any other object in the entire language. That woudl be perverse.

----------


## kleinma

> A string was a reference type in 2003, and did not act like an integer. I haven't looked in 2005, but I assumed it was the same thing.
> 
> The behavior you are seeing for strings is not what should be happening. Strings should act the same as the dataset, not the same as an integer. Are you sure you have actually seen this for strings? You would have to do a bit of testing, but this should not be happening.
> 
> In pretty nearly all languages, a string is nothing but the address of the first character in the string (this isn't quite true, but it is true enough, so don't lets have those technical folks jump on me for being a bit casual). The string starts at that byte, and continues on until it reaches a termination character. Thus the size of the string variable is the size of a four byte memory address, regardless of the length of the actual string. If what you are saying were true, then when you assigned one string to another:
> 
> string1 = string2
> 
> Then the equal sign would have to dereference string2, figure out the length of string2, allocate sufficient memory to hold a string of that length, copy each byte of string2 into that new memory, and put the address of the first byte of that new memory in string1. To put it simply: It ain't very likely!!
> ...


Yes strings are still reference types in 2005. You will modify its contents in a calling routine regardless of the fact of being passed ByRef or ByVal

----------


## Shaggy Hiker

Well, that has strayed a bit. Are there any other Form to Form issues I should cover in the initial post?

----------


## kleinma

Perhaps you might want to just brush on default instances? I think you mentioned you are using VB 7.1, and they didn't come back until VB8, so let me know if you want me to write a blurb about them.

----------


## Shaggy Hiker

Yes, know very little about default instances, but my impression of them is that it makes things a bit too easy for folks, while masking some of their understanding. I certainly don't know enough about them to say anything rational about them. In fact, I am only vaguely aware that they exist.

----------


## kleinma

Well most people say they were added back in to help VB6 people move to .NET (that may or may not be true, I haven't seen MS actually say that anywhere)

Basically a default instance of a form is the same as creating your own instance of a form. The only difference is that you don't use a variable to hold the reference, you use the forms actual name.

So lets say you start a new project. By default it will add in a Form1 for you.

So in VB 2005 you have the option to either do

Dim MyForm as New Form1
MyForm.ShowDialog

or you can do

Form1.ShowDialog

what happens is the runtime says "Is the default instance of Form1 nothing? if it is create a new instance, if not use the existing instance"

Situations that it is good for, are situations like a login form, an options form, etc...

GENERALLY you are never going to show 2 login forms at the same time in an app are you? So the default instance can be handy here because you can simply just call the show method of the login form. If you always call the login form using its name, you will always access the default instance.

You can also assign the default instance of a variable of the forms type, since its all reference types, if you wanted to for any reason...

So as long as you understand what default instances are, they are actually pretty nice and useful in certain situations. If you don't understand, then you will run into situations where you get unexpected results.

I think the reason people don't like them is because they think it is against standard OO practices. VB is known for making things easier on the developer though, and for being IMO the best RAD tool out there, so the more they can do to make it easy the better.

Hell most of the methods in the My namespace (also new to 2005) are available via other standard framework classes. Does that mean you shouldn't use the My namespace? depends on if it makes your life as a developer easier or not  :Wink:

----------


## daemonk

well I'll do a quick test on the string reference stuff when I get home I guess. I did a test on that before and I thought the string value was copied. Maybe I screwed something up. What I did to test it last time was:

-Add public member AString and BString into AForm and BForm respectively.
-Then I added this to the main form:

dim AFo as new AForm
Afo.Astring = "String A"
messagebox.show(AFo.AString)   'should show String A in a messagebox

dim BFo as new BForm
BFo.BString = Afo.Astring
messagebox.show(BFo.BString)  'should show String A in a messagebox

Afo.Astring = "Changed String A"

messagebox.show(AFo.AString)  'shows Changed String A in a messagebox
messagebox.show(BFo.BString)  'shows Cahnged String A in a messagebox

----------


## Shaggy Hiker

Uhhhhh, isn't that exactly what you were saying didn't happen? In your example, changing one instance changed them both, which is what should happen for a reference type.

Kleinma: After reading that, I can sum up my feelings about default instance with one word: Ugh!

Ok, it is what I thought it was, and works the way I thought it worked. I also think that it was added back in as a convenience. When I used that in VB6, I used it without understanding it. That is a convenience, and perhaps it will remain a harmless convenience, but I feel that it will cause confusion for anybody who tries to do anything that gets beyond the default instance. If people become trained to think that Form1 is the name of the form, rather than the name of the class, then they will become confused when they need to make multiple instances of the class.

I haven't used My yet, either.

As far as passing data from Form to Form, it appears that using the default form, you probably can't use an overloaded constructor, as the default constructor must take no arguments. Perhaps that could be altered by removing the default constructor.

What this means is that the default instance has to transfer data using properties, as far as I can see.

----------


## kleinma

I like to think of it as an implied shared instance. Think of it as just a feature of the form class.... the ability for it to create an instance of itself via a shared method.. it just happens that the shared method can be any public method of the form to instantiate the instance.

Yes, since you don't use a constructor with a default instance, you would use properties for data exchange. You could call that a limitation, but again, default instances should really only be used in isolated instances, if at all.

----------


## Shaggy Hiker

Ok, I edited the first post to include a little bit about how the default instance requires you to move data via properties.

At this time, I think that first post covers all of the key points about transfering data between forms.

----------


## nbrege

Kleinma ... this is from your post #11:




> ```
> Dim MyForm as New Form1
> MyForm.SomeProperty = True 'BETTER NOT FORGET TO SET THIS
> MyForm.ShowDialog
> ```



Can you please explain this method a little better?  In particular, what is .SomeProperty?  Is it an existing property of a form or is it a new property that you create?  If it's a new property, how do you create it?


If I want to use this method:



```
Dim MyForm as New Form1(True)
MyForm.ShowDialog
```

In this example, Form1 is passing a value of "True" to Form2.  But how do I retrieve that value once Form2 is displayed?  Also, can I pass any data type using this method (string, integer, etc.)?

Thanks...

----------


## kleinma

It is some property you create USUALLY, but it could be an existing property of the form if you wanted it. Since the constructor (new sub) you create can take whatever params you tell it to, you can set whatever properties you want in the constructor. So here is an example setting an existing AND custom property of a form

So lets say in the form you make the custom constructor for you have this code:



```
    Private _CustomProperty As String = String.Empty

    Public Property CustomProperty() As String
        Get
            Return _CustomProperty
        End Get
        Set(ByVal value As String)
            _CustomProperty = value
        End Set
    End Property

    Public Sub New(ByVal CustomPropValue As String, ByVal FormBackColor As Color)

        InitializeComponent()

        Me.CustomProperty = CustomPropValue
        Me.BackColor = FormBackColor

    End Sub
```

then in the form you call this form from, you have this code.



```
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim F As New Form2("HELLO WORLD", Color.Red)
        F.ShowDialog(Me)
        F.Dispose()
    End Sub
```

as you can see, I pass 2 values, and I assign them in the forms New sub to the correct properties.

----------


## Shaggy Hiker

> Kleinma ... this is from your post #11:
> 
> 
> 
> 
> Can you please explain this method a little better?  In particular, what is .SomeProperty?  Is it an existing property of a form or is it a new property that you create?  If it's a new property, how do you create it?
> 
> 
> If I want to use this method:
> ...


The point Kleinma was making with the first part of that post was that using properties to pass data is sometimes not such a good idea, because you might forget that you need to pass the data. By overloading the constructor, you can pass the data directly to the form as you would with any argument to any sub or function. If you then make the default version of the constructor private, you can make it impossible to create the form without passing the data.

----------


## sytto

First great site! I have found some of the responses here invaluable, thanks to all who make this forum such a valuable resource.

Little history on me, i stopped VB programming around the time VB6 was dropped by MS and back then I only programmed very little C, lots of VB 5 and 6 then my wife starting running this baby making program which pretty much sucked all my time and resources dry - lol. The programming bug struck again this summer as I found I have a little more time now that the kids are a  little more independent so i thought i would take a boo at VB 2005.

Yikes. So much has changed and initially could not understand why there wasn't this or that, as an example control arrays. I promptly bought a few books and am getting my head around things and sites like this have helped tremendously. I have written many, many little programs in VB 2005 and decided to write something that i could actually use, meaning a little more complex.

OK to the point. :-)

I have a main form, I call a second form to set some variables which will be used for the duration of that programs session within the main form. The easiest thing would have been to use global variables in a module, but often I read that is not he way to do things and of no challenge to do so, yes i mainly just like the challenges of programming. 

Above i read about class object (seems popular), is the code example above basically a class object but in a forms class? Currently i am setting labels on the main form and setting them with a new instance of form 2, then setting main forms variables with those filled in labels. I want to use a class object, is there any sample program i can check that anyone knows of?

----------


## Hack

I think it is about time this got moved to the CodeBank (if for no other reason than an easy point of reference   :Smilie:  )

_Moved_

----------


## kleinma

yeah.. the question only gets asked 100 times a day  :Wink:

----------


## Hack

> yeah.. the question only gets asked 100 times a day


 :LOL:    That is how I found the thread...there is a question on this in the .NET section at this very moment.   :Big Grin:

----------


## Pradeep1210

> Yes strings are still reference types in 2005. You will modify its contents in a calling routine regardless of the fact of being passed ByRef or ByVal


Ummm...
It doesn't seem to be modifying the contents of the passed string.

vb.net Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click        Dim myString As String = "Some String"        MsgBox("My Original value is: " & myString)        LetsTestString(myString)        MsgBox("After LetsTestString, my value is: " & myString)    End Sub     Private Sub LetsTestString(ByVal theString As String)        theString = "LetsTestString modified me"        MsgBox("In LetsTestString: " & theString)    End Sub
When we run the above code, it shows that _LetsTestString_ did not change the value original string value that was passed. i.e. it made the changes in a different memory location.

Though strings are reference types in .NET, they don't quite behave as such.
Instead they behave more like value types rather than reference types. They are mutable. One string can't change the contents of another string even if they are pointing to the same memory location. As soon as you try to do that, .NET will create a new memory location and make it point there.

----------


## kleinma

> Though strings are reference types in .NET, they don't quite behave as such.
> Instead they behave more like value types rather than reference types. They are mutable. One string can't change the contents of another string even if they are pointing to the same memory location. As soon as you try to do that, .NET will create a new memory location and make it point there.


you are correct. To be honest, I am not sure why I said that originally (was 2 years ago). Although one thing to note is strings are actually immutable, not mutable.

----------


## kareninstructor

When adding an overloaded new constructor to a form it will never show up in the Project properties Startup form ComboBox. It should not matter but thought it prudent to mention. If you want it to show up then add a default new constructor along with the overloaded new constructor.  For anyone who wants to try this out download the attachment, which has two, projects and load them. No need to build either project but instead look at the Startup ComboBox and note one form is missing in both. In the temp project note there is no form1 but it shows up in the Startup form ComboBox which happened when Form1 was removed then the form with an overloaded new constructor was added. Any ways I thought this was interesting as it happened to a fellow developer who asked me what was going on. 

To me this is a non-issue unless you are not sure what the heck is going on.

----------


## techgnome

There's a reason for that... When the application starts, it creates an instance of the form. As such, there isn't a way to pass parameters to the constructor of the form ... after all, how would it know what to send to the form? That's why you need to have a parameterless constructor of the form. So the IDE removes any form that doesn't have a parameterless constructor. 

-tg

----------


## catoctinwx

I'm still fairly new at VB (using VB .NET for the moment) and I have a question that I didn't see addressed in this thread.

I'm trying to pass a bunch of variables from one form to another.  In other languages I have used, I've been able to build a structure (although I'm not sure how to do that in VB yet).  For single variables I have been using the code that has been mentioned in this thread:

Private ReadOnly Property _PassMetFile1() As String
    Get
        Return firstmet.Text
    End Get
End Property

and

Friend WriteOnly Property _ReceiveMetFile1() As String
    Set(ByVal value As String)
      metfile1 = value
    End Set
End Property


I am not trying to pass about 25 fields from one form to another and I obviously don't want to go through those statements all 25 times.

Is there a way to build all 25 fields into one variable and pass it from one form to another?

Thanks

----------


## techgnome

you can pass it as a List(Of String) ... you can use a custom class... or a structure... or an array even....

-tg

----------


## Shaggy Hiker

You can certainly create a class or structure and pass that. You would be changing the property to take a member of that class or structure type rather than a string, but it would otherwise work the same. If all the items you want to pass are strings, I would agree with TG that you should just pass a List(of String).

In any case, you may have just as much trouble populating a structure as you would passing 25 different values individually. Of course, there would be more code involved adding those 25 properties onto the form, but once you had done that, passing the values would be easier than filling a structure then passing the structure....unless your code is such that the structure can be filled for other reasons such that you get more benefit from having the structure than just to simplify passing it around.

----------


## techgnome

Of course that also asks the question why so much needs to be passed over? Surely there's a better way ...

-tg

----------


## catoctinwx

Thanks for the all the suggestions.  I'm going to try to use the List(Of String) approach and see how that works.  If it fails, I'll just pass everything over individually.

The reason that I need to pass a bunch of data is that I am creating an environment to run a program with a lot of variables.   Generally the program will be run with default values and I won't need to the user to change them, but they need the ability to modify it if they want.  

So, I made a seperate page to modify the default values.  If they change them, then when they close that page, VB will use those new values instead of the default ones.

----------

