P
Peter Duniho
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