Event handlers in c# - syntax/pattern - c#

I'm new to c# so apologies if this is a noob question. I'm trying to get clarity around the syntax or pattern for handling events in c#.
So I have a Form object Form1 and a Button button1 in the form. I handle a Click event with a method like this in Form1.cs:
private void button1_Click(object sender, EventArgs e)
{
Debug.WriteLine("click!");
}
which works fine. Now in another form Form2 I have a TreeView treeView1, and I want to handle the BeforeExpand event. So I assumed it would be:
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
Debug.WriteLine("Hello!");
}
which in fact doesn't work: this method is never called when I expand a node. But several SO answers imply this is the way to do it, e.g this one.
Anyway I found an alternative approach which does work for me. In the form constructor bind the event handler like this:
treeView1.BeforeExpand += new TreeViewCancelEventHandler(anyMethodNameYouLike);
So what's the difference between these two approaches? Why doesn't the _event syntax work for a treeview? Is there some difference between the event types?
Thanks

I assume you doubleclicked the button in the Visual Studio designer. The button1_Click handler got added automatically, just like you created the BeforeExpand handler by hand.
Check your Form1.Designer.cs file, you'll find a line something like this:
this.button1.Click += new System.EventHandler(this.button1_Click);

You need both things:
1) a method that can handle the type of event in question. For a TreeViewCancelEventHandler(MSDN) delegate the correct method signature is:
public void MyMethodNameGoesHere(Object sender,TreeViewCancelEventArgs e)
{
// do some impressive stuff here
}
2) you have to register for the event:
treeView1.BeforeExpand += new TreeViewCancelEventHandler(MyMethodNameGoesHere);
You could also use just the method name:
treeView1.BeforeExpand += MyMethodNameGoesHere;
And as a last alternative you might use this 'inline' syntax for small functions:
treeView1.BeforeExpand += (sender, e) =>
{
// do a bit of magic here
};
What is possibly good to know is that handler registrations don't 'stack' (sorry for the poor wording, suggestions for improvement are very welcome!).
Meaning when you do the following you will not receive further events after the last line has executed:
treeView1.BeforeExpand += MyMethodNameGoesHere;
treeView1.BeforeExpand += MyMethodNameGoesHere;
treeView1.BeforeExpand += MyMethodNameGoesHere;
treeView1.BeforeExpand -= MyMethodNameGoesHere; // note the MINUS sign

What you have is correct. You need to add the the handler to the event as you have done in the second case.
There must be a line like this:
button1.Click += button1_Click;
(possibly with a new EventHandler() wrapper) somewhere in your Form1 code, most probably in the .designer.cs file.

The first syntax, which isn't syntax at all, is just a naming convention for event handlers. What you're doing with the second syntax is setting up a delegate to an event handler and adding it to that event.
If you check Form1, and click select the Button and look at its events properties, the event is most likely hooked up through the designer. You could do the same with the TreeView on its form, through the designer.

The C# event handling system does not work on any sort of naming convention (I think you may believe this to be the case?). A method called treeView1_BeforeExpand will not be called on treeview1's BeforeExpand event unless you tell it to call that method on that particular event.
The code below says "when the BeforeExpand event is fired, invoke the anyMethodNameYouLike method.
treeView1.BeforeExpand += new TreeViewCancelEventHandler(anyMethodNameYouLike);
You have to write your anyMethodNameYouLike method.

In WinForms, you can bind event handlers from the designer using the "properties" toolbox and clicking the lightning button at the top. This will open the events tab. Just double click on the name of an event to generate an handler in your code or select an existing method with the right signature from the dropdown. This will actually generate the "+=" code for you in the .designer file.
The name Control_Event is automatically generated. However, you can use any name for your handlers and even register more than one.

That is the correct way to subscribe to an event. The designer automatically adds that line to the .designer.cs file when you subscribe to the event via it.
Either way, this line of code is getting written somewhere. The difference is one event is being subscribed to via the designer, while the other you are subscribing to manually.

Related

C# DotNetBar switchButton not working

So, I would double click here on my designer
and it should create me the code, but well it doesn't. And there is no value changed event in the events either.
So if anyone knows how to fix this, it would be nice. (I doubt it) so how would I get around this? How would I go on about creating the code myself that should be created when I double click on it?
Click the form or control that you want to create an event handler for.
In the Properties window(F4), click the Events button
In the list of available events, click the event that you want to create an event handler for.
In the box to the right of the event name, type the name of the handler and press ENTER.
Add the appropriate code to the event handler.
To create an event handler in the code editor
Switch to the code editor by using one of the following techniques:
Create a new method like:
private void buttonName_Click(object sender, EventArgs e) { ... }
In the file YourFormName.Designer.cs find your button and add
this.buttonName.Click += new System.EventHandler(this.buttonName_Click);

Fire an event within another event

I need help on firing an event within C#
Basically I have a onclick event that fires when you click on a checkbox
void OnClick(object sender, RoutedEventArgs e)
{
...
}
I need help on firing an event within C#
Basically I have a onclick event that fires when you click on a checkbox
void OnClick(object sender, RoutedEventArgs e)
{
...
}
However, I need to fire this event once another event has been fired, so within this new event, is it possible I can fire the above one?
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
switch(dataGrid.Name)
{
case "Customer"
//fire OnCLick Event
break;
}
}
I have tried something like
??? += new MouseEventHandler(OnClick);
But I am not sure if this will actually work.
Yes you can, but only if the event is in your own class. You can't even raise a base class' event. You have a put a method in the base class to raise the event, and then call that.
The code you put there is adding another event handler, not raising an event; you don't need to do that.
If it's a button, use btnDoSomething.PerformClickEvent (winforms)
If the handler is in your code, you can call it without raising the event (commenters assume that this is what you want to do but in reaslity there are many cases where you'd need more than this) btnDoSomething_Click(null, null) - null usually works because handler code rarely cares about the sender or arguments and if you don't reference them, you don't need them.
If you can use #4, you can also refactor as mentioned. Usually not needed. But usually so easy to do you it's worth doing for clarity anyway.
For objects that map from Windows widgets of anysort, check out the SendMessage and PostMessage API calls. Wayyyy beyond the scope of this answer, though. Doesn't apply to non-windows-backed objects (but your sample implies windows).

Detecting a left button mouse click Winform

What I'm trying to do is get my winform to display a debug line when ever I click in my winform. However, when I do, nothing happens. I know how to get a button / other click event to happen. But what I need is to be able to click anywhere within my winform.
I've googled this for the past hour but can't see what I'm doing wrong. As far as I'm aware, this code should be correct in detecting a mouse click. This method is held withing the form1.cs class:
private void mouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
Trace.WriteLine("Mouse clicked");
}
I've tried setting brake points, but these don't get triggered either. What is it I'm doing wrong?
Sorry for the stupidly newbie question, but I am very new to winform programming.
How to add the EventHandler:
public Form1()
{
InitializeComponent();
// This line should you place in the InitializeComponent() method.
this.MouseClick += mouseClick;
}
Using the editor built-in to Visual Studio:
Go to the properties window (if you don't see it, press Alt + Enter).
Select the events icon (looks like lightning).
Double-click on the empty ComboBox to the right of Click.
You'll be taken to an empty method where you can put your code.
The method itself is correct. I think your actual problem is: you haven't added this method to MouseClick events.
In C# – and most other languages too – event is handled by an event handler. Windows forms and controls have events for all the events happening in your controls, such as OnClick or OnResize.
You can append methods to these events, and the methods will automatically get called when the actual event happens. Simply add the following line to your form's constructor, Form_Load-method, InitializeComponent-method, or such:
this.MouseClick += mouseClick;
Now when ever MouseClick event happens, your method mouseClick will be called automatically.
I would recommend reading Events C# Programming Guide. You need to add an event handler like so:
form1.MouseClick += mouseClick;

Change button on-click event creating exponetially increasing events

Have a simple application with a start/stop button that I want to do different things depending on it's current state. If button is in Start state, execute code then change to stop state and change OnClick event to StopButton_Click and vice versa.
Can't seem to change the on-click property of the button, so using code below which works, but keeps adding instances of the event. First click executes once, second click executes twice, third executes four times, ad infinitum.
StartButton.Click += new System.EventHandler(StartButton_Click);
alternates with
StartButton.Click += new System.EventHandler(StopButton_Click);
Is there a way to REPLACE the OnClick handler instead of adding to it?
Try removing the event handler before adding a new one:
StartButton.Click -= StartButton_Click;
One option is to remove the previous event handler before adding another, but a simpler option is to just use a single event handler. The event handler can look at some internal state field to determine what to do; this will likely be easier than constantly adding/removing event handlers.
It may look something like this:
private void buttonClick(object sender, EventArgs args)
{
if(buttonState == MyStateEnum.Start)
PerformStartAction();
else if(buttonState == MyStateEnum.Stop)
PerformStopAction();
}
Then instead of adding/removing event handlers you just need to assign a different value to buttonState.
+= works with events as it does anything else. It adds to what is already there.
Try removing the existing event handler with -= and then adding the new one.

How do I find out if a particular delegate has already been assigned to an event?

I have a command button on a winform. So, if I have something like:
myButton.Click += MyHandler1;
myButton.Click += MyHandler2;
myButton.Click += MyHandler3;
How can I tell if any particular MyHandler has already been added to the Click event so it doesn't get added again somewhere else in my code?
I've read how you can use GetInvocationList() for your own event's information. But I get errors when trying to get the items for my command button using various combinations. It says,
"The event
'System.Windows.Forms.Control.Click'
can only appear on the left hand side
of += or -=."
What am I missing?
[Edit] - I'd like to accentuate this question that Ahmad pointed out. It's a kludge and should be easier IMHO, but it looks like it might just work.
If you're in doubt if your handler is already added then just remove it and add it again. If your handler wasn't added in the first place, your removal is just ignored.
myButton.Click -= MyHandler1;
myButton.Click += MyHandler1;
You could also create one method for attaching to an event, and make sure that the code is only run once.
private bool handlersAdded;
private void AddHandlers()
{
if (this.handlersAdded) return;
myButton.Click += MyHandler1;
this.handlersAdded = true;
}
The use of GetIvocationList can only be done from within the owner of the event (myButton in your case), that's one of the ideas behind events (as opposed to delegates).
Like Slugster said, you can't check the invocation list from outside myButton, but you can try and remove MyHandler# before adding it.

Categories

Resources