I am working a problem which is about delegate and event. I am a newbid in this aspect. I don't know how to call the event.
Would some tell me?
Thanks in advance.
Here is simple example to call event....
// event_keyword.cs
using System;
public delegate void MyDelegate(); // delegate declaration
public interface I
{
event MyDelegate MyEvent;
void FireAway();
}
public class MyClass: I
{
public event MyDelegate MyEvent;
public void FireAway()
{
if (MyEvent != null)
MyEvent();
}
}
public class MainClass
{
static private void f()
{
Console.WriteLine("This is called when the event fires.");
}
static public void Main ()
{
I i = new MyClass();
i.MyEvent += new MyDelegate(f);
i.FireAway();
}
}
There is Link which may helpful.
The event can be invoked in the class in which it is declared. First you'll usually want to check if your event is null.
if (MyEvent != null) MyEvent(this, new EventArgs());
The arguments you pass to the event will depend on the declaration of the event. To give you a little more background, an event is just a compiler trick. When an event such as
public event ChangedEventHandler Changed;
is compiled it will look like
protected ChangedEventHandler _change;
public ChangedEventHandler Change
{
add { _change += value; }
remove { _change -= value; }
}
so anything inside where it is declared will use _change, while anything outside will use Change. In other words, inside where it is declared, it is just a delegate, and all the normal rules apply.
To resuse the event you just need to attach event with the you control for example .
buttonone.Click+= event1;
buttonTwo.Click+= event1;
Fore more details have look : C# Event Implementation Fundamentals, Best Practices and Conventions
Once you have defined the delegate, you need to define when to call the event. I mean you can call the event at assignment of any value to the specific variable.
here is the example of defining the delegate with the same variable class.
public class callbackdel : EventArgs
{
public readonly string resp = null;
public callbackdel(string s)
{
resp = s;
}
}
public delegate void WorkerEndHandler(object o, callbackdel e);
Now in the control you are using, you need to add this method.
public void OnWorkEnd(object o, callbackdel e)
{
WorkEnd(o, e);
}
after creating method and defining the delegate, you can fire the event from any of the delegate simply by calling the method.
OnWorkEnd((object)this, e);
When using an Event you first have to declare it:
// Create some custom arguments for the event
public class SampleEventArgs
{
public SampleEventArgs(string s)
{
Text = s;
}
public String Text {get; private set;}
}
// Define a class that uses the event
public class EventPublisher
{
// Declare the delegate
public delegate void SampleEventHandler(object sender, SampleEventArgs e);
// Declare the event.
public event SampleEventHandler SampleEvent;
// Wrap the event in a protected virtual method
// to enable derived classes to raise the event.
protected virtual void RaiseSampleEvent()
{
// Raise the event by using the () operator.
if (SampleEvent != null)
SampleEvent(this, new SampleEventArgs("Hello"));
}
}
You can then subscribe to the event:
EventPublisher publisher = new EventPublisher();
publisher.SampleEvent += new EventPublisher.SampleEventHandler(SampleEventHandler);
public void SampleEventHandler(object sender, SampleEventArgs args)
{
}
Your event handler will be called when EventPublisher executes RaiseSampleEvent()
Related
What would be the equivalent C# code against following VB.Net code:
Public Event EndOfVideo()
Private Sub RaiseEndOfVideo()
RaiseEvent EndOfVideo()
End Sub
EDIT
Here is the equivalent C# code that telerik converter generated for me.
public event EndOfVideoEventHandler EndOfVideo;
public delegate void EndOfVideoEventHandler();
private void RaiseEndOfVideo()
{
if (EndOfVideo != null) {
EndOfVideo();
}
}
Calling RaiseEndOfVideo doesn't trigger/invoke EndOfVideo event, and Null Reference Exception is raised.
Consider you have class VideoPlayer which has event EndOfVideo and you want to raise this event and when someone calls method EndVideo on object of VideoPlayer.
Now, like any other member of a class event also initialized to null and gets the value when some handler is attached to it.
Attaching an handler to an event happens using += operator.
public class VideoPlayer
{
public event EndOfVideoEventHandler EndOfVideo;
// Following delegate indicates that the a method accepting no parameter
// and returning void can be attached as an handler to this event.
public delegate void EndOfVideoEventHandler();
public void EndVideo()
{
RaiseEndOfVideo();
}
private void RaiseEndOfVideo()
{
if (EndOfVideo != null)
{
// Following line of code executes the event handler which is
// attached to the event.
EndOfVideo();
}
}
}
public class WebPage
{
public void VideoStopped()
{
Console.WriteLine("Video Stopped");
}
}
Now in Main method of program.cs
static void Main(string[] args)
{
VideoPlayer player = new VideoPlayer();
WebPage page = new WebPage();
player.EndOfVideo += page.VideoStopped;
// Following method call on player object will call internally
// RaiseEndOfVideo which will Raise event and event will execute
// VideoStopped method of page object which is attached in previous line
// and display "Video Stopped" message in Console.
player.EndVideo();
Console.WriteLine("Completed!!! Press any key to exit");
Console.ReadKey();
}
I hope this would help you start understanding how events and delegates work in C#. For further reading you can go thru https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx
This is the generally accepted way to write an event with no parameters:
public class Foo
{
public event EventHandler EndOfVideo;
protected virtual void OnEndOfVideo()
{
var handler = EndOfVideo;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
Your code is what was needed in the old days: creating a delegate and yada yada.
To state the obvious, though, you need to subscribe to an event with something like:
public class Bar
{
public void DoAllTheThings()
{
var foo = new Foo();
foo.EndOfVideo += foo_EndOfVideo;
}
void foo_EndOfVideo(object sender, EventArgs e)
{
Console.WriteLine("EndOfVideo");
}
}
For the sake of completeness, the EventHandler delegate has a generic counterpart, EventHandler<T>, which you would use when you want an event that does have parameters, where T should be a class inheriting from System.EventArgs which holds the information you want your event to expose.
To do that, you will need to create a custom eventHandler to specify the method signatures of the handlers for your event
Please forgive my little knowledge!
I have the following class in HIDNewDeviceEventMonitor.cs:
public class HIDNewDeviceEventMonitor : IDisposable
{
// used for monitoring plugging and unplugging of USB devices.
private ManagementEventWatcher watcherAttach;
public HIDNewDeviceEventMonitor()
{
// Catch USB HID plugged instance event watching
watcherAttach = new ManagementEventWatcher();
watcherAttach.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcherAttach.Query = new WqlEventQuery(#"SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_PNPEntity' AND TargetInstance.DeviceID LIKE 'HID\\VID_04D8%'");
watcherAttach.Start();
}
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
Debug.WriteLine("my device is inserted..");
}
public void Dispose()
{
watcherAttach.Stop();
watcherAttach.Dispose();
}
~HIDNewDeviceEventMonitor()
{
this.Dispose();
}
}
Now, how can I change this class to be able to add an event handler that the class can call from within watcher_EventArrived where someNewEvent is outside the class file, actually in the form.cs:
// code in the form
HIDNewDeviceEventMonitor ok = new HIDNewDeviceEventMonitor();
ok.Inserted += someNewEvent; // <-- my problem, I don't know how to add an event to the class this way
private void someNewEvent()
{
//Enumerate and add to listbox1
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ok.Dispose();
}
I 've seen this thing with other classes, how can I make my class like that?
Your Inserted event should look like this:
public event EventHandler Inserted;
You invoke it like this:
private void OnInserted()
{
if (this.Inserted != null)
{
this.Inserted(this, EventArgs.Empty);
}
}
The signature for the event handler is this:
void someNewEvent(object sender, EventArgs e)
{
//
}
Then you should wrap that code in the constructor of the class:
HIDNewDeviceEventMonitor ok;
public ClassName()
{
ok = new HIDNewDeviceEventMonitor();
ok.Inserted += someNewEvent; // <-- my problem
}
Declare the ok variable outside the constructor, and instantiate it inside. Then add the event handler.
Pro tip: You could use the generic EventHandler<T> if you need to supply a custom implementation of e.
Simply put, you're trying to add events to your HIDNewDeviceMonitor class.
To do this, first you'll need to define a delegate.
public delegate void InsertedHandler;
Next, you'll need to define the event in your HIDNewDeviceMonitor class.
// Notice how the event uses the delegate that's been defined
// v
public event InsertedHandler Inserted;
Now you'll need something that "fires" the event, which could easily be put in your watcher_EventArrived method.
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
Debug.WriteLine("my device is inserted..");
// Notice how we check the event handler for null.
// If you don't, it could throw a NullReferenceException.
// Irritating, but easy to debug.. Usually..
if (Inserted != null)
Inserted(); // Or whatever parameters you need.
}
We're all done with the HIDNewDeviceMonitor class.
Now whatever class that uses the HIDNewDeviceMonitor can use the EventHandler code that you provided.
However, it'll have to be the same delegate.
public class MyClass
{
HIDNewDeviceMonitor monitor;
public MyClass()
{
monitor = new HIDNewDeviceMonitor();
monitor.Inserted += DeviceInserted;
}
private void DeviceInserted()
{
// Execute code here
}
}
You need to do following in the HIDNewDeviceEventMonitor class:
1.) First define a public event inside the class like this-
public event EventHandler Inserted;
2.) Then fire this event within the code where you detect the changes in events. Like this-
if(Inserted != null)
Inserted(this,null);
The if condition checks if the event is registered by any listener. It's fired in case it is.
Hope this helps.
I have my custom EventArgs in a separate class file that I can reference it later from different classes:
using System;
using System.Collections.Generic;
namespace SplitView
{
public class RowSelectedEventArgs:EventArgs {
public Patient selectedRow { get; set; }
public RowSelectedEventArgs(Patient selectedRow) : base(){
this.selectedRow = selectedRow;
}
}
}
In my MasterViewController I defined my event
public event EventHandler<RowSelectedEventArgs> RowClicked;
In DataSource which is in MasterViewController I can raise the event:
if (this.controller.RowClicked != null) {
this.controller.RowClicked (this, new RowSelectedEventArgs (this.controller.list [indexPath.Row]));
}
As you can see I have a field (controller) in my DataSource with which I reference the event. Now I have a SearchSource with the same concept (also field called controller). Now in SearchSource I want to raise the event:
if (this.controller.RowClicked != null) {
this.controller.RowClicked (this, new RowSelectedEventArgs (this.list [indexPath.Row]));
}
But I get
The event 'SplitView.MasterViewController.RowClicked' can only appear
on the left hand side of += or -= when used outside of the type
'SplitView.MasterViewController'
The only difference is that SearchSource is not part of the class MasterViewController (as it is with DataSource). But the event is public so it should work?
How can I raise the same event from different classes?
You can't directly raise an event outside of the type, which defines this event.
All you can do, is a method, which will raise event from outside:
public sealed class MyClass
{
// this should be called from inside
private void OnSomeEvent()
{
var handler = SomeEvent;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
// this should be called from outside
public void RaiseSomeEvent()
{
OnSomeEvent();
}
public event EventHandler SomeEvent;
// other code here...
}
Is the field conroller in SearchSource also fo type MasterViewController?
It seems that it is a different type.
I have a set of events that have the same signature . now I wonder if I can create a generic event handler raising method to do this for all of the events ?
is this possible to send an event as <T> ?
If this is all within a single class, you can make a method to raise the event which works with any of them. For example, if your events all were EventHandler<T>, you could use:
private void RaiseEvent<T>(EventHandler<T> eventHandler, T eventArgs)
{
if (eventHandler != null)
{
eventHandler(this, eventArgs);
}
}
You could then call this via:
this.RaiseEvent(this.MyEvent, new MyEventArgs("Foo"));
For a static version of Reed Copsey's reply, I created a static class Event:
public static class Event
{
public static bool Raise<T>(Object source, EventHandler<T> eventHandler, T eventArgs) where T : EventArgs
{
EventHandler<T> handler = eventHandler;
if (handler != null)
{
handler(source, eventArgs);
return true;
}
return false;
}
}
This also assumes your event handlers are of the type EventHandler<T>. The return type was changed from void to bool and returns whether there were any listeners of the event. Rarely used, so feel free to change back to void.
Example usage:
public event EventHandler<FooArgs> FooHappend;
public void Foo()
{
Event.Raise(this, FooHappend, new FooArgs("Hello World!");
}
See this. It describes what you want.
You can create a typed event by using a typed delegate and using that for your event:
public delegate void myDel<T>(T stuff);
public event myDel<int> myEvent;
public doStuff()
{
myDel(1);
}
Say I have a class just for specifying C# events and I pass this class around my application.
public class MyEvents
{
public event MyEventHandler OnBeforeSomeAction;
public event MyEventHandler OnSomeAction;
}
In order to invoke these events the invocation has to come from within the class itself. The easy way to let other classes trigger these events as MyEvents gets passed around the application would be to create public trigger functions.
public class MyEvents
{
public event MyEventHandler OnBeforeSomeAction;
public event MyEventHandler OnSomeAction;
public void TriggerOnBeforeSomeAction()
{
OnBeforeSomeAction();
}
public void TriggerOnSomeAction()
{
OnSomeAction();
}
}
However, if there are many events on this class then there would also have to be many trigger methods. Would there be a way to get the event using reflection and trigger it? Something like this:
public class MyEvents
{
public event MyEventHandler OnBeforeSomeAction;
public event MyEventHandler OnSomeAction;
public void TriggerEvent(string eventName)
{
var event = // some magic reflection.
event.Invoke();
}
}
Exactly what you want - taken from this fantastic page....
public void TriggerEvent(string handler, EventArgs e)
{
MulticastDelegate eventDelegate =
(MulticastDelegate)this.GetType().GetField(handler,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue(this);
Delegate[] delegates = eventDelegate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, new object[] { this, e });
}
}