How to handle form events in C#

6 views
Skip to first unread message

mena...@hotmail.com

unread,
Aug 26, 2007, 2:36:59 AM8/26/07
to
Hello,

I am absolute beginner in C# so pardon me if the following question is
too easy.

I have a form with a one button. When I click the button I want to
display a message that reads "Button was clicked"
However, I do not want to handle the click event from that form,
instead I want to "transfer" that event to a "controller" class that
shows that message.

The ides is this:
Have a class (call it "controller")
Controller opens the form
When I click the button the controller is "notified" by the form that
the button was clicked
The controller displays the message "Button was clicked"

Now, how do I accomplish this?

Thank you, Richard

Alberto Poblacion

unread,
Aug 26, 2007, 3:14:28 AM8/26/07
to
<mena...@hotmail.com> wrote in message
news:1188110219....@m37g2000prh.googlegroups.com...

> I have a form with a one button. When I click the button I want to
> display a message that reads "Button was clicked"
> However, I do not want to handle the click event from that form,
> instead I want to "transfer" that event to a "controller" class that
> shows that message.
>
> The ides is this:
> Have a class (call it "controller")
> Controller opens the form
> When I click the button the controller is "notified" by the form that
> the button was clicked
> The controller displays the message "Button was clicked"
>
> Now, how do I accomplish this?

One way to accomplish this is to publish an event in your form. When the
controller opens the form, it subscribes to the event of the form. In the
click event of the button, the only action that you take is to fire the
event that you published in your form. In this way, it gets "relayed" to the
controller.


Richard_AU

unread,
Aug 26, 2007, 3:38:03 AM8/26/07
to
Alberto,
Thank you for your reply
As I have mentioned I am a beginner with C# so I
need some code exmples.
"publish an event", "subscribe to the event" etc
what is the code that you use in your form and what
is the code that you use in your controller class?


"Alberto Poblacion" <earthling-quitae...@poblacion.org> wrote
in message news:%23jWyGD7...@TK2MSFTNGP04.phx.gbl...

Yaron Karni

unread,
Aug 26, 2007, 4:10:16 AM8/26/07
to
public class From
{
public event EventHandler BtnClicked;

private void Clicked(object o , eventrags e)
{
if(BtnClicked != null)
BtnClicked (o,e) ;
}
}

public class Controller
{

private void OpenFrom()
{
From frm = new From ();
frm.BtnClicked += new EventHandler(FromClickedHander);
Frm.shopw();
}

private void FromClickedHander(object o , eventrags e)
{
.....
}

}
--
Sincerely
Yaron Karni
http://dotnetbible.blogspot.com/

Peter Duniho

unread,
Aug 25, 2007, 9:33:31 PM8/25/07
to
mena...@hotmail.com wrote:
> Hello,
>
> I am absolute beginner in C# so pardon me if the following question is
> too easy.
>
> I have a form with a one button. When I click the button I want to
> display a message that reads "Button was clicked"
> However, I do not want to handle the click event from that form,
> instead I want to "transfer" that event to a "controller" class that
> shows that message.

That's fine. By default, when you double-click on a button, the VS
Designer creates a new method in the same form and adds some code to the
InitializeComponent() method that subscribes that method to the event.

But the delegate method that gets subscribed to the event can be any
delegate method from any class (as long as the method has the correct
signature, of course...that is, it has a "void" return type, and two
parameters, the first an "object" and the second an "EventArgs").

In general, you need a method that looks like this:

void ClickHandler(object sender, EventArgs e) { ... }

And you need a reference to the button:

Button button = ...;

To subscribe, you just do this:

button.Click += ClickHandler;

Of course, the actual names can be anything you want. Also, since the
Click event is in the Control class, your variable need not actually be
of type Button; it can be Control if you like...you just have to make
sure you get the right control instance somehow.

If you set a Click handler the usual way in the Designer, and then go
look at the InitializeComponent() method, you'll see it does essentially
the same thing as the above.

On the assumption that your controller class is the one instantiating
form in the first place, it would be easy enough to subscribe to the
event at that time, from the controller class itself. The event is just
a member on the button, called "Click".

The one thing that's problematic is that, by default, control instance
variables in the form class are private. So the controller class would
not normally have direct access to the button's reference. However,
there are a number of ways around this:

* Make the button instance variable public. This is simply a
matter of setting the appropriate property in the Designer ("Modifiers"
under the "Design" category of properties). Then the controller can
access it through the form class, using the actual name of the variable.

* Enumerate the child controls. You can use Find() or similar on
the Form.Controls collection and look for the button control with the
name you want to watch. Once you have a reference to the instance, it's
a simple matter to subscribe to the event.

* Define some sort of API in the form class through which you can
pass a delegate instance to be subscribed to the button.

* Make the controller's handler method visible to the form class,
and let the form subscribe the handler to the event.

Finally, yes...you could do as Alberto suggests and define a whole new
event on the form class to which the controller can subscribe, and then
have the form mediate between that event and the button itself. But
IMHO, that's a waste. Your controller class can easily subscribe
directly to the button's event, and creating an event is -- while not
that difficult -- certainly an added complication that is in this case
wholly unnecessary.

Note that this is not a complete list. They are just some of the more
straightforward ways to deal with the issue. Which one is more
appropriate may well depend on other aspects of your design (for
example, you may not feel it's appropriate for the form class itself to
do things that seem like "controlling the controller", such as the
fourth item above).

Hopefully this gets you pointed in the right direction.

Pete

Alberto Poblacion

unread,
Aug 26, 2007, 5:47:23 AM8/26/07
to
"Richard_AU" <Ric...@nospam.com> wrote in message
news:v5aAi.26256$4A1....@news-server.bigpond.net.au...

> As I have mentioned I am a beginner with C# so I
> need some code exmples.
> "publish an event", "subscribe to the event" etc
> what is the code that you use in your form and what
> is the code that you use in your controller class?

To publish an event inside your form, you declare it inside your class
like this:

public event EventHandler TheButtonClicked;

You then "fire" it from the click of the button:

protected void Button1_Click(object sender, EventArgs e)
{
if (TheButtonClicked!=null) TheButtonClicked(this, e);
}


The "controller" subscribes a routine to handle the event connecting the
routine to the event after creating the form:

TheForm f = new TheForm();
f.TheButtonClicked += new EventHandler(MyRoutine);
f.Show();
...

private void MyRoutine(object sender, EventArgs e)
{
//Do something here
}

Richard_AU

unread,
Aug 26, 2007, 6:40:52 PM8/26/07
to
Thank you everyone for your assistance I now understand how to use this
events mechanism.

I got it to work but there is a little problem.
I can make it work if I create another form and from that form I load my
"controller" class.
How can I load my "controller" class when the application starts?
That is,when I start my application on the C# IDE it will load my controller
class, as a result my controller class opens my form.
Then if I click a button on that form it will instruct my controller class
to unload (resulting in closing my form)?

Thanks for you help
Richard

<mena...@hotmail.com> wrote in message
news:1188110219....@m37g2000prh.googlegroups.com...

Message has been deleted

Richard_AU

unread,
Aug 26, 2007, 7:33:43 PM8/26/07
to
Peter,

Thank you for this exmplanation
Any chance of a small code example?


Richard

"Peter Duniho" <NpOeS...@NnOwSlPiAnMk.com> wrote in message
news:13d42ir...@corp.supernews.com...


> Richard_AU wrote:
>> Thank you everyone for your assistance I now understand how to use this
>> events mechanism.
>>
>> I got it to work but there is a little problem.
>> I can make it work if I create another form and from that form I load my
>> "controller" class.
>> How can I load my "controller" class when the application starts?
>

> You mean, how do you get your controller class to actually be able to act
> as the controller class, instead of the controlled class? :)
>
> This is simple to do, once you understand the structure of the default C#
> program when created within Visual Studio. The entry point for your
> program is the Main() method found in the Program class, which is in the
> Program.cs file. Check your Solution Explorer pane to find this easily.
>
> In the Main() method, you'll want to change the code that by default looks
> something like this:
>
> Application.Run(new Form1());
>
> Instead, you'll probably want to do something like instantiate the
> controller class, let it instantiate your initial form, let the controller
> class subscribe to whatever events are appropriate at the time, and _then_
> call Application.Run() with the form instance that the controller created.
> You could even have the controller class itself make the call to
> Application.Run(), which could give it a little more control over
> application shutdown. Or you could have a method in the controller class
> that returns the initial form.
>
> Or, you could even have a static method in the controller that does all of
> the instantiation of the controller and the initial form and then returns
> that initial form.
>
> If you did the latter, then the only change to the Program.Main() method
> might look something like this:
>
> Application.Run(Controller.FormStartup());
>
> where the Controller.FormStartup() method creates the actual controller
> instance, creates the initial Form instance, subscribes the controller
> instance methods to the initial Form's event as necessary, and then
> returns the reference to the Form instance.
>
> Now, all that said...
>
> For yet another perspective on how this might work: I don't think it'd be
> the end of the world if you just wanted the initial form's constructor to
> instantiate the controller. Yes, it would mean that the controller itself
> isn't really doing the instantiation of the initial form, which seems a
> little backwards. It also means that the form class winds up perhaps
> knowing more about the controller than would normally be the case. But as
> long as the controller semantics are otherwise adhered to, I don't think
> that devalues the use of a controller class.
>
> In fact, if you make the controller a singleton class with the usual
> static Instance property, you can either instantiate the controller lazily
> (on the first call to the Instance property getter), or in a static
> constructor for the class. Either way would allow you to not only leave
> the default Program.Main() method as-is, but would also avoid having the
> controller's instantiation explicitly tied to code within your initial
> form; _any_ form that ever accesses the controller class could be used and
> the controller class would get created implicitly in the process.
>
> So, for example, you might design it so that rather than the controller
> class creating that initial form, the form "registers" itself with the
> controller in its constructor, allowing the controller to at that time do
> whatever event subscription, etc. it needs to do. You could in fact make
> that the design for all forms; controlled instances always need to
> register themselves, which is the point at which the controller then hooks
> up whatever event handling, etc. it wants.
>
> IMHO, "design patterns" such as singleton, controller, etc. are for your
> benefit. Adhering closely to them is often the best way to get the most
> value out of them, but if there seems to be a benefit in deviating a
> little from the pattern, and you can do so knowing exactly what
> implications that has with respect to the overall design, I don't think
> it's terrible to do so. Better to deviate a little, than to corrupt some
> other part of the design just to get the design pattern to be exact (not
> that I think that changing Program.Main() is a corruption...in this case
> it's just a matter of what seems easier or cleaner to you).
>
> Pete


Peter Duniho

unread,
Aug 26, 2007, 7:56:30 PM8/26/07
to
Richard_AU wrote:
> Thank you for this exmplanation
> Any chance of a small code example?

Of what? One downside of my rambling is that I offered a number of
design possibilities. You haven't narrowed the question down much from
my broad offering. :)

That said, I would probably go with the "static method in controller
class returning the form" design, if it were me. That might look
something like this:

class Program
{
static void Main()
{
// ... VS-supplied initialization
Application.Run(Controller.FormStartup());
}
}

class Form1 : Form
{
// this would be your usual Form-derived class.

// I've assumed that you've simply made the button
// instance public for the purpose of subscribing
// to its events.
}

class Controller
{
public static Form FormStartup()
{
Controller controller;
Form1 form1;

controller = new Controller();
form1 = new Form1();
form1.button1.Click += controller.ClickHandler;
return form1;
}

private void ClickHandler(object sender, EventArgs e)
{
// do whatever in response to click event here
}
}

Hope that helps,
Pete

Richard_AU

unread,
Aug 26, 2007, 8:30:18 PM8/26/07
to
Very good
Thank you so much Peter I finally got it to work.

Richard

"Peter Duniho" <NpOeS...@NnOwSlPiAnMk.com> wrote in message

news:13d44pf...@corp.supernews.com...

Reply all
Reply to author
Forward
0 new messages