How to access a public method from another class?

R

RickL

Hi,

Suppose I create a Windows Form app and then add a public method
like this:

class Form1 : Form
{
// Constructors, etc.

public void DoSomethng()
{
}
}

Now I add a UserControl to the form, add a button to the UserControl
and a Click handler for the button.

Question:
When I click the button, how do access the DoSomething() method
in the Form1 class?

I tried this in the UserControl, but the DoSomething() method is not
visible.

private void button1_Click(object sender, EventArgs e)
{
this.Parent.DoSomething(); ???? the method is not visible.
}


Thanks for any help.
RickL
 
B

Bruce Wood

RickL said:
Hi,

Suppose I create a Windows Form app and then add a public method
like this:

class Form1 : Form
{
// Constructors, etc.

public void DoSomethng()
{
}
}

Now I add a UserControl to the form, add a button to the UserControl
and a Click handler for the button.

Question:
When I click the button, how do access the DoSomething() method
in the Form1 class?

I tried this in the UserControl, but the DoSomething() method is not
visible.

private void button1_Click(object sender, EventArgs e)
{
this.Parent.DoSomething(); ???? the method is not visible.
}

First, I'll tell you why the method is not visible, and how to make it
visible. Then I'll go on about why this is a poor solution to the
problem, and propose a more complicated (but better) solution.

So... why doesn't

this.Parent.DoSomething()

work? It doesn't work because this.Parent is declared as a Control (or
a ContainerControl... I don't recall). Anyway, it's not declared as an
instance of your particular form class. Now, you and know that at
runtime it will be (well, we think we know... more on that later), but
the compiler doesn't know that.

In order to gt access to DoSomething, you have to "promise" the
compiler that this.Parent is an instance of Form1. You do that like
this:

Form1 myForm1Parent = (Form1)this.Parent;
myForm1Parent.DoSomething();

the cast (Form1) says to the compiler, "I promise that at runtime this
will be an instance of Form1. If it's not, you can throw an exception
and blow my program out of the water."

However, this is not a good solution to the problem. It's not a good
solution because how do you know for sure that your UserControl will
always be placed directly on a Form1? What if someone decides it's very
useful and puts it on a Form2 for some other purpose? It will die on
that statement:

Form1 myForm1Parent = (Form1)this.Parent;

because its parent is no longer a Form1.

The correct (although more complex) solution is to have your
UserControl raise an event, then have Form1 handle that event and call
its own DoSomething() method. Something like this:

public event System.EventHandler UserWantsInformation;

private void button1_Click(object sender, EventArgs e)
{
if (this.UserWantsInformation != null)
{
this.UserWantsInformation(this, System.EventArgs.Empty);
}
}

.... and you already know how to hook this up in Form1 so that Form1
listens for the "UserWantsInformation" event from the UserControl and
then calls DoSomething() in its own event handler. Added bonus:
"DoSomething" can now be private to Form1.

This is a better solution, because now your UserControl can be placed
on any form, and it is the form's job to decide what to do when the
UserControl signals a condition.

(I'm assuming, of course, that the event coming from the UserControl
has some name indicating what the user wants; I chose
UserWantsInformation at random. Just don't call it UserClickedButton,
which is truly lame. :)
 
O

Otis Mukinfus

On 22 Jul 2006 12:22:29 -0700 said:
First, I'll tell you why the method is not visible, and how to make it
visible. Then I'll go on about why this is a poor solution to the
problem, and propose a more complicated (but better) solution.

So... why doesn't

this.Parent.DoSomething()

work? It doesn't work because this.Parent is declared as a Control (or
a ContainerControl... I don't recall). Anyway, it's not declared as an
instance of your particular form class. Now, you and know that at
runtime it will be (well, we think we know... more on that later), but
the compiler doesn't know that.

In order to gt access to DoSomething, you have to "promise" the
compiler that this.Parent is an instance of Form1. You do that like
this:

Form1 myForm1Parent = (Form1)this.Parent;
myForm1Parent.DoSomething();

the cast (Form1) says to the compiler, "I promise that at runtime this
will be an instance of Form1. If it's not, you can throw an exception
and blow my program out of the water."

However, this is not a good solution to the problem. It's not a good
solution because how do you know for sure that your UserControl will
always be placed directly on a Form1? What if someone decides it's very
useful and puts it on a Form2 for some other purpose? It will die on
that statement:

Form1 myForm1Parent = (Form1)this.Parent;

because its parent is no longer a Form1.

The correct (although more complex) solution is to have your
UserControl raise an event, then have Form1 handle that event and call
its own DoSomething() method. Something like this:

public event System.EventHandler UserWantsInformation;

private void button1_Click(object sender, EventArgs e)
{
if (this.UserWantsInformation != null)
{
this.UserWantsInformation(this, System.EventArgs.Empty);
}
}

... and you already know how to hook this up in Form1 so that Form1
listens for the "UserWantsInformation" event from the UserControl and
then calls DoSomething() in its own event handler. Added bonus:
"DoSomething" can now be private to Form1.

This is a better solution, because now your UserControl can be placed
on any form, and it is the form's job to decide what to do when the
UserControl signals a condition.

(I'm assuming, of course, that the event coming from the UserControl
has some name indicating what the user wants; I chose
UserWantsInformation at random. Just don't call it UserClickedButton,
which is truly lame. :)

Very good and easily understood answer Bruce. Thank you.

Good luck with your project,

Otis Mukinfus
http://www.arltex.com
http://www.tomchilders.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top