Re: How to pass information, classes between forms in Windows Application mode
- From: Jon Skeet [C# MVP] <skeet@xxxxxxxxx>
- Date: Tue, 22 Jul 2008 22:49:35 +0100
raylopez99 <raylopez99@xxxxxxxxx> wrote:
Alternatively, Form2 could have a parameterless constructor and you
could set properties, or call methods to pass it the information.
Constructors aren't the only way to pass information between objects.
What are the other ways?
I just listed two: call a method, set a property. You mentioned some
others yourself. My point is that your claim on the first message of
this thread:
<quote>
If you want to pass information between two forms comprised of
classes, whether or not they are parent/child, modal or modeless,
dialog or non-dialog you have to use the non-normal/ non-default or
parametricized or parameter constructor, not a default (no parameter)
normal constructor.
</quote>
is incorrect. A constructor is *one* way of passing information, but
not the only way.
Passing a class that has a method X that
accepts other classes is of course one way, but for all practical
purposes it's the same as the parameterized copy constructor
Be careful here - you haven't created any copy constructors. Giving
constructors parameters isn't the same as creating a copy constructor.
with the important difference of course that you can call this method
X many times, not just once. Another way is the inheritance of forms,
Form2: Form1 as you discuss below and as I further comment below.
Another way maybe is the publisher-subscriber events/delegates model?
But I'm not sure, since Forms, unlike Console mode, has some tricks
to it (discussed below).
There's not really a "Console mode" beyond whether or not a console is
allocated at startup. You can display GUIs in console applications.
Furthermore, the language itself really doesn't care about all of this
- parameter passing, constructors etc remain consistent whatever you're
doing (with some oddities around remoting and the like, admittedly).
I'm not entirely sure you're correct [UPDATE: after running the tests
below, I'm sure that a person--not you--but a person who says an
object that is passed to Form2 using the parametric constructor of
Form2 from Form1 is not passing the true object but a copy of the
object is not correct]
You're neither passing "the true object" nor a copy of the object.
You're passing a reference to the object.
Yes, because we're dealing with a managed language C#. Is that your
point? OK. A small point but noted.
No, it's not a small point at all. It lies at the heart of what you're
seeing when it comes to what you're calling data binding.
if you say myClass2_that_exists_in_Form2 cannot
"actually refer to the Form1.myClass1 'variable' from Form2, since we
are passing by value, so it must refer to it.
No, not at all. You have passed the current value of the variable as
the argument. If you change the value of Form1.myClass1, there will be
no way for Form2 to retrieve it. It doesn't have access to the
*variable*.
Not true. You might have something else in mind. I am finding out
that both in what I call the non-inherited model of Form1: Form and
Form2: Form, where I use a parameterized constructor to pass the
class2 that has the information in it, and the inhereited model of
Form2: Form1, that you suggested, I am getting "data binding" between
the two forms in both directions.
No, you're not. You can't make any changes to the *variable* of one of
the forms. Sure, you can make changes to the object that the variable
originally refers to, but you can't make the variable refer to a
different object completely (unless you use a ref parameter to start
with, of course - and then only during that call).
That is, with one small, trivial
bug exception that I discuss below with inherited controls, I am
getting both the public variable arr2 of Class2 to 'update' in both
the Form1 (parent) and Form2 (child) when I make a change to arr2 in
either parent or child forms (Forms 1 or Form 2, respectively).
Well, you haven't shown any code with a variable called arr2 in.
However, I strongly *strongly* suspect that you're not changing the
value of the variable - you're changing the contents of the array.
Unless you have
arr2 = [some value];
you're not changing the value of arr2. Certainly this:
arr2[0] = [some value];
isn't doing it. The value of arr2 is just a reference - and that
reference doesn't get changed just because you're changing the contents
of the array, any more than your home address changes if you decorate a
bedroom.
It's very important to understand the difference between a variable,
its value, and the object it happens to refer to at a particular point
in time.
That
is data binding in both directions. It's working. The small
exception? When I inherit forms, Form 2 gets all the controls from
Form1 (which BTW is very confusing and I would never do this in
practice, but it's just a demo), and because of some obscure way form
controls are instantiated, or perhaps something else, when I try and
update arr2 using the inherited child form control button (but not the
parent form control button), I get an 'old' value. But this is a
minor bug or rather just an inherited control problem, or some small
thing. The main thing is that using my system or your system I am
getting data binding in both directions.
Another use of incorrect terminology: data binding isn't what you think
it is.
However, you can't take
an arbitrary reference to an instance of Form1 and access its myClass1
variable from Form2, while the variable is private.
Yes. You keep saying this, and this is a newbie point well taken, but
we (I) am beyond that. One funny thing I keep forgetting is that C#
likes to always express access modifiers everywhere, with no access
modifier being private by default. But for this example I set
everything to public, using keyword 'public'. Everything, so this
point is moot? (but see the note at the end here about 'class0')
When the fields are public then yes, you can change the values of
variables (so long as you have a reference to an instance of the
containing class, of course).
But, as we know, if you add the "ref" keyword, and with a
helper function we can change a class (we can put the helper function
in another class, or as a standalone function, that accepts 'ref
Class2'), however, the issue here is (and this may or may not be what
you have in mind) whether to use the above example
"myClass2_that_exists_in_Form2" can permanently change any public
variable in class "passClass2[1]_from_Form1", via changes made in
Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]
Reference parameters do effectively change the situation somewhat, but
it's important to note that Form2 doesn't really know that it's
Form1.myClass1 that's been passed to it by reference. It could be a
local variable, or a variable from something completely different.
It could be, but for some reason, like I said, when you change the
parameter in Form 2, form Form1 is also updated, even when the forms
are not inherited. If you feel this fact is shocking, unjustified,
unexplained or whatever, let me know and I'll post the code. I think
it's routine myself--just conventional data binding when you pass one
class (or variable) to another. I'll tell you what I feel is
shocking, below (keep reading--keyword 'class0' and 'nested classes').
Yes, nested classes have access to private members in their enclosing
class. That's not shocking to me, because it's part of the spec. As for
the rest, it's a simple matter of understanding the difference between
an object and a reference.
Rather than me explaining reference parameters here, I suggest you read
my article on them:http://pobox.com/~skeet/csharp/parameters.html
This is the article that I mentioned that I already have btw. It
doesn't explain much for this forms example.
Your forms example is still massively incomplete.
You still seem confused about the difference between passing a
reference by value and passing a parameter *by* reference. Changing the
*contents* of an object doesn't change the value of a variable which
refers to that object.
Agreed. So? I don't seem confused over that.
Yes, you do. You keep claiming to be able to change the value of a
variable you don't have access to, just because you can change the
contents of the object that the variable happens to refer to. They're
not the same thing.
OK, here is what I found "shocking". I took your suggestion and for
one version of this program I used inheritance, like I said above, as
in Form1: Form and Form2: Form1 <--note the inheritance (the other
version, which also works, uses two 'independent' forms Form1: Form
and Form2: Form). Both the inherited and non-inherited versions use
the parametricized constructor to pass classes 1 and 2, but,
crucially, I added a third class, class 0, that was nested. This
class 0 was nested and declared public (twice) within Form1, and thus
could be 'seen' (by Intellisense, and ultimately by the program)
unlike declared Classes 1 and 2 (using "Add" to the Solution), which
had their own modules/translation units, unnested, outside of Form1.
This is part of the problem - instead of trying to isolate one single
piece of how the language behaves, you're coming up with massive
examples with non-descriptive names (Class1, Class2, Class3, Form1,
Form2) and making them *much* more complicated than they need to be.
Why involve designer classes (which you never post), partial classes,
inheritance *and* nested classes all in the same example? Stick to one
at a time, preferably in a simple Console app which doesn't require any
extra code. Your examples would be *much* clearer that way.
Your code is even incomplete in the non-designer classes - you haven't
shown where Form2 is declared.
Specifically, consider 'nested' class 0 as follows, which is properly
seen by base Form 1 and derived Form2. Comments //!! below
namespace MDIForms
{
public partial class Form1 : Form
{
Class1 myClass1; //though these are public, do they now become
'private' since no keyword public? That is the question!
Class2 aNew2Class; // " "
public Class0 myClass0; // !! keyword 'public' required!!
Shocking, no?!!
Required to do what? To see it from Form2? No, it can be private. It
can also be declared anywhere in the class, even after the nested
class, contrary to your later assertion. Here's an example:
using System;
class Test
{
static void Main()
{
Test t = new Test();
t.privateVariable = "private";
new Nested().ShowPrivateVariable(t);
}
class Nested
{
internal void ShowPrivateVariable(Test t)
{
Console.WriteLine(t.privateVariable);
}
}
private string privateVariable;
}
That example is *complete* - you can cut and paste it into a new text
file, then run csc on it and run the resulting executable. I would
greatly appreciate it if you would follow the same model. At the moment
it's like being asked to guess which number you're thinking of.
//note!!! 'FORWARD DECLARATION STEP'
Why are you still using terminology that you're aware is incorrect?
<snip incomplete code>
Perhaps, and I could use your input, the problem 'earlier' in this
thread is that classes 1 and 2, which are not nested, are not
explictly declared prior to the Form1 contructor with the keyword
'public', and, though in their respective modules I declare them as
'public', this makes them 'private' somehow when declared within Form
1 without the keyword 'public' (that is truly shocking if true).
Thanks for your help so far. I look forward to your reply.
If you would post a short but *complete* program which demonstrates
something strange.
Note that there's a big difference between declaring a *variable* as
public and declaring a *class* as public. In the paragraph above you
seem to be conflating the two ideas.
--
Jon Skeet - <skeet@xxxxxxxxx>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
.
- Follow-Ups:
- References:
- How to pass information, classes between forms in Windows Application mode
- From: raylopez99
- Re: How to pass information, classes between forms in Windows Application mode
- From: Jon Skeet [C# MVP]
- Re: How to pass information, classes between forms in Windows Application mode
- From: raylopez99
- Re: How to pass information, classes between forms in Windows Application mode
- From: Jon Skeet [C# MVP]
- Re: How to pass information, classes between forms in Windows Application mode
- From: raylopez99
- Re: How to pass information, classes between forms in Windows Application mode
- From: Jon Skeet [C# MVP]
- Re: How to pass information, classes between forms in Windows Application mode
- From: raylopez99
- How to pass information, classes between forms in Windows Application mode
- Prev by Date: Microsoft Report Viewer with SqlConnection
- Next by Date: Re: User control refactoring (WPF)
- Previous by thread: Re: How to pass information, classes between forms in Windows Application mode
- Next by thread: Re: How to pass information, classes between forms in Windows Application mode
- Index(es):