- Home /
How do i declare an event listener?
Ok, two seperate classes.
First of all, there's my SelectionManager class, it governs selecting of units (isometric/topdown game) and i want it to fire off an event whenever the selection changes.
I'm using this to define the event:
public delegate void SelectionEventHandler(GameObject justSelected);
public event SelectionEventHandler SelectionChanged;
And i'm using this line to fire off an event
SelectionChanged(active);
This compiles without errors, but i've not been able to test it.
Secondly, the other class, this one is named FixedCamera It contains a reference to the instance of my SelectionManager class (the reference variable is named "selectionManager")
I'm attempting to define a listener on the aforementioned event, like this:
selectionManager.SelectionChanged += new SelectionEventHandler(SetSubject);
However this won't compile, SelectionEventHandler has a red underline. The tooltip error is: "The type or namespace "SelectionEventHandler" could not be found..."
My obvious first thought then, is that it doesn't know where to look, so i tried this
selectionManager.SelectionChanged += new selectionManager.SelectionEventHandler(SetSubject);
However this throws a different error "selectionManager is a field, but is used like a type"
I'm stumped. What am i not getting?
Answer by Xarbrough · Apr 20, 2015 at 12:06 PM
Try this:
//class SelectionManager
public delegate void SelectionEvent (GameObject selected);
public static event SelectionEvent OnSelectionChanged;
//class Listener
SelectionManager.OnSelectionChanged += HandleNewSelection;
void HandleNewSelection(GameObject selected) {
//
}
You're event should be static, so that it is available everywhere. Next you can just assign a method to your delegate.
It most certainly does not need to be static. Example co$$anonymous$$g up.
Edit: Done writing example. :) See my answer. To clarify my response to this: If you make the event static, then you're detaching it from the objects which are instances of the class. It becomes common for them all. This could be useful, I suppose, if all the class's instances should all share the same handler for that event. But there are tons and tons of use cases for events where that is not at all what you want. Imagine, for example, if the event handler for a GUI button was static. Then all buttons across your entire GUI would do the same thing when you clicked them. :)
Valid point. $$anonymous$$y argument for static events is that in this case it works like a "global" event that only fires for a single action, namely the selection of the current unit. In a global manager with only a few events, this is a nice and easy approach. For everything else I would go with CHPedersen's approach.
That's fair enough. :) (downvote removed). Though, the typical approach to object selection is to have e.g. OnSelected events associated with the object instances rather than a global manager. Just like something like "On$$anonymous$$ouseEnter" is associated with each instance of $$anonymous$$onoBehaviour. But one could argue that concerns the pattern OP followed rather than his issue with calling syntax, so your answer is correct.
Just want to add that "SelectionEventHandler" is a nested-type. So if you want to use it outside the Selection$$anonymous$$anager scope you have to use the "class name" to get the inner class.
selection$$anonymous$$anager.SelectionChanged += new Selection$$anonymous$$anager.SelectionEventHandler(SetSubject);
Note the upper case "S" so we use the class, not the reference to the instance. You never use an instance reference when you want to access a type.
Type definitions are "static stuff", so to access a nested type (enum, class, delegate, struct, ...) use the classname of the outer class followed by the nested classname seperated with a dot.
See the last paragraph over here
Another solution is to define your delegate type outside of your Selection$$anonymous$$anager class so the type will be part of the current namespace scope. You should only nest types if they are truly only used in combination of the outer class. So when it's a type that comes with that class and is only ment to be used with that class.
If it's a more general type definition it should not be a nested type.
Answer by CHPedersen · Apr 20, 2015 at 12:38 PM
What you have is almost correct. I have an event declared like below. Disregard that its name has data and buffers and what not in them, that's because it's actual code I just copy-pasted from a project. At later stages, I will replace the EventArgs with a custom class that holds my own event arguments, of course. But this demonstrates the pattern, at least.
public delegate void DataProcessedDelegate(object sender, EventArgs e);
public event DataProcessedDelegate OnDataProcessed;
I fire it the same way you do, except that you should check it against null first. An event is null if it has no listeners attached:
if (OnDataProcessed != null)
OnDataProcessed(this, new EventArgs());
A listener (event handler) is attached like so:
WRSProcBuffer buffer = new WRSProcBuffer(2048); // Irrelevant, this is just for the sake of the example
buffer.OnDataProcessed += buffer_OnDataProcessed;
Where the handler itself is a method with a signature that matches the arguments declared in the delegate:
void buffer_OnDataProcessed(object sender, EventArgs e)
{
// Triggered when the event is raised
}
What do you mean an event is null if it has no listeners? will it throw an error, or is that just a performance consideration?
i don't understand what you're doing with the attaching a listener, and how it differs from my example. what is WRSProcBuffer?
I mean it is null, as in, it will throw a NullReferenceException if you attempt to raise an event that has no listeners. As for WRSProcBuffer, forget about that. That's just a classname specific to my project only. It's here because this example comes from actual code in my project. I explained that in the beginning of this reply. :-)