I have two classes, and i have to make an event to communicate between these classes.
Class a
{
public delegate void delegat(int a);
public event delegat exit;
...
private void a_FormClosed(object sender, FormClosedEventArgs e)
{
// My event named exit should run here, but I get exception!
exit(100);
}
}
Class b
{
a instance=new a();
a.exit+=new a.delegat(my_fun);
...
private void my_fun(int x)
{
if(x==100)
do_smth;
...
}
}
But the thing is that i get exception: "object reference not set to an instance of an object".
I can't understand what Am I doing wrong? Where should I make a new instance of this?
Thanks for help!
You are trying to assign the exit event on the class itself and not the instance e.g.
a.exit += ...
Should be:
instance.exit += ...
You also aren't checking whether your exit event has been assigned before attempting to fire it. There are other issues which you haven't taken into consideration like race conditions.
Here is a general example of a relatively safe way of handling events e.g.
public class A
{
public delegate void ExitHandler(object sender, int a);
public event ExitHandler Exit;
...
private void a_FormClosed(object sender, FormClosedEventArgs e)
{
OnExit(100);
}
protected virtual void OnExit(int a)
{
// take a reference to the event (incase it changes)
var handler = Exit;
if (handler != null)
{
handler(this, a);
}
}
}
public class B
{
private A _a;
public B()
{
_a = new A();
_a.Exit += (sender, value) => my_fun(value);
}
private void my_fun(int x)
{
if(x==100)
do_smth;
...
}
}
I would change "class a" code for calling the event to as follows:
Class a
{
public delegate void delegat(int a);
public event delegat exit;
...
private void a_FormClosed(object sender, FormClosedEventArgs e)
{
if (this.exit != null) // just in case a_FormClosed fires before assigning the event
exit(100);//here should run my event named exit but i get exception!
}
}
Verify if there is any subscriber exist to your event before raising it:
if (exit != null)
exit(100);
Another option - subscribing dummy event handler when you are defining event in class A:
public event delegat exit = (_) => { };
Also use PascalCase naming for types, events and methods. And there is predefined delegate in .NET which receives one argument and returns void: Action<T>
Try this
namespace foo
{
public delegate void delegat(int a);
Class a
{
public event delegat exit;
private void a_FormClosed(object sender, FormClosedEventArgs e)
{
if(exit != null)
{
exit(100);//here should run my event named exit but i get exception!
}
}
}
}
Class b
{
a instance=new a();
instance.exit+=new delegat(my_fun);
...
priavte void my_fun(int x)
{
if(x==100)
do_smth;
...
}
}
Related
I have this class that contain several events that from my main i register and update my UI:
public class MyClass
{
public delegate void event1Delegate();
public event event1Delegate event1Handler;
public delegate void event2Delegate();
public event event2Delegate event2Handler;
public delegate void FinishWorkDelegate();
public event FinishWorkDelegate FinishWorkEventHandler;
public void DoWork()
{
// bla bla
if (FinishWorkEventHandler != null)
FinishWorkEventHandler();
}
}
And from my main UI register to this events inside my button clock event:
private void radMenuItemSimultaneouslyPlay_Click(object sender, EventArgs e)
{
MyClass obj = new MyClass();
job.event1Handler += job_event1Handler;
job.event2Handler += job_event2Handler;
job.FinishWorkEventHandler += job_FinishWorkEventHandler;
job.doWork();
}
Now when FinishWorkEventHandler fired this means that my operation done:
private void job_OnFinishJobThreadEvent()
{
labelStatus.Text= "Finished!";
}
And here i want to unsubscride to MyClass events so i wonder if it's OK to change this event from FinishWorkDelegate() into FinishWorkDelegate(MyClass obj) and that from here i have access to my object and in this case i can unsubscride to my events.
Is it OK to do that ?
Is it OK to do that ?
Yeah why not ? in fact there is already a built-in delegate for this called EventHandler<T>, instead of creating a new delegate you can use that:
public event EventHandler<EventArgs> FinishWorkEventHandler;
public void DoWork()
{
// bla bla
if (FinishWorkEventHandler != null)
FinishWorkEventHandler(this, EventArgs.Empty);
}
Here you can replace this with your current instance (if you want to trigger it from outside of the class ofcourse) and then pass it to event handler.in the event handler you can access your object like this:
private void OnFinish(object sender, EventArgs e)
{
var myObject = sender as MyClass;
if (myObject != null)
{
myObject.event1Handler -= job_event1Handler;
myObject.event2Handler -= job_event2Handler;
}
}
I declare a subscription to event in:
public class MainClass
{
public void btndel_bar_Click(object sender, RoutedEventArgs e)
{
SomeClass sc = new SomeClass();
sc.FieldUpdate += new SomeClass.FieldUpdateHandler(sc_FieldUpdate);
}
void sc_FieldUpdate(object sender, ValueEventArgs e)
{
MessageBox.Show(e.Smth_property);
}
}
And here is I want to listen event:
public class Someclass
{
public delegate void FieldUpdateHandler(object sender, ValueEventArgs e);
public event FieldUpdateHandler FieldUpdate;
void Somemethod()
{
string str = "Steel";
ValueEventArgs args = new ValueEventArgs(str);
FieldUpdate(this, args);
}
}
A class which carries data:
public class ValueEventArgs : EventArgs
{
private string smth;
public ValueEventArgs(string smth)
{
this.smth = smth;
}
public string Smth_property
{
get { return smth; }
}
}
I always have FieldUpdate=null. How to solve it?
You're calling Somemethod() in the constructor, before the calling code gets a chance to add the event handler.
Therefore, the event is still null.
The moment you create the object of SomeClass your event would get reinitialized.
Make your event a static so that multiple objects of SomeClass would share it
public static event FieldUpdateHandler FieldUpdate;
I've read articles about delegates and events and after reading I always I thought to make all operations again. I did all over again and it works! Consequently I done something wrong when I did at the beginning of.
This question already has answers here:
How to raise an event on Property Change?
(2 answers)
Closed 7 years ago.
I have
class A
{
B b;
//call this Method when b.Button_click or b.someMethod is launched
private void MyMethod()
{
}
??
}
Class B
{
//here i.e. a button is pressed and in Class A
//i want to call also MyMethod() in Class A after the button is pressed
private void Button_Click(object o, EventArgs s)
{
SomeMethod();
}
public void SomeMethod()
{
}
??
}
Class A has a instance of Class B.
How can this be done?
You'll need to declare a public event on class 'B' - and have class 'A' subscribe to it:
Something like this:
class B
{
//A public event for listeners to subscribe to
public event EventHandler SomethingHappened;
private void Button_Click(object o, EventArgs s)
{
//Fire the event - notifying all subscribers
if(SomethingHappened != null)
SomethingHappened(this, null);
}
....
class A
{
//Where B is used - subscribe to it's public event
public A()
{
B objectToSubscribeTo = new B();
objectToSubscribeTo.SomethingHappened += HandleSomethingHappening;
}
public void HandleSomethingHappening(object sender, EventArgs e)
{
//Do something here
}
....
You need three things (which is marked by comments in code):
Declare event in class B
Raise event in class B when something happened (in your case - Button_Click event handler executed). Keep in mind that you need to verify if there are any subscribers exists. Otherwise you will get NullReferenceException on raising event.
Subscribe to event of class B. You need to have instance of class B, which even you want to subscribe (another option - static events, but those events will be raised by all instances of class B).
Code:
class A
{
B b;
public A(B b)
{
this.b = b;
// subscribe to event
b.SomethingHappened += MyMethod;
}
private void MyMethod() { }
}
class B
{
// declare event
public event Action SomethingHappened;
private void Button_Click(object o, EventArgs s)
{
// raise event
if (SomethingHappened != null)
SomethingHappened();
SomeMethod();
}
public void SomeMethod() { }
}
Have a look at rasing an event from Class B
Have a look at
Raising an Event
Handling and Raising Events
How to: Raise and Consume Events
I have created a very simple dummy program to understand Delegates and events. In my below program I am simple calling a method. When I call a method, five methods are automatically called with the help of delegates and events.
Kindly take a look at my program and do let me know where I am wrong or right as this is my first time using delegates and events.
using System;
namespace ConsoleApplication1
{
public delegate void MyFirstDelegate();
class Test
{
public event MyFirstDelegate myFirstDelegate;
public void Call()
{
Console.WriteLine("Welcome in Delegate world..");
if (myFirstDelegate != null)
{
myFirstDelegate();
}
}
}
class AttachedFunction
{
public void firstAttachMethod()
{
Console.WriteLine("ONE...");
}
public void SecondAttachMethod()
{
Console.WriteLine("TWO...");
}
public void thirdAttachMethod()
{
Console.WriteLine("THREE...");
}
public void fourthAttachMethod()
{
Console.WriteLine("FOUR...");
}
public void fifthAttachMethod()
{
Console.WriteLine("FIVE...");
}
}
class MyMain
{
public static void Main()
{
Test test = new Test();
AttachedFunction attachedFunction = new AttachedFunction();
test.myFirstDelegate += new MyFirstDelegate(attachedFunction.firstAttachMethod);
test.myFirstDelegate += new MyFirstDelegate(attachedFunction.SecondAttachMethod);
test.myFirstDelegate += new MyFirstDelegate(attachedFunction.thirdAttachMethod);
test.myFirstDelegate += new MyFirstDelegate(attachedFunction.fourthAttachMethod);
test.myFirstDelegate += new MyFirstDelegate(attachedFunction.fifthAttachMethod);
test.Call();
Console.ReadLine();
}
}
}
Events are implemented using Delegates. That said by convention events take the form of:
void EventHandler(Object sender, EventArgs args);
EventHandler is actually a delegate defined in .Net. EventArgs is a class in .Net that acts as a placeholder to pass additional information. If you have additional information you would create a class that derived from EventArgs and contained properties for the additional data; therefore you would create your own delegate like so:
void MyEventHandler(Object sender, MyEventArgs args);
Microsoft has a tutorial on events here and also describes defining and raising events here
This is a common pattern with dealing with events:
// define the delegate
public delegate void CustomEventHandler(object sender, CustomEventArgs e);
// define the event args
public class CustomEventArgs : EventArgs
{
public int SomeValue { get; set; }
public CustomEventArgs( int someValue )
{
this.SomeValue = someValue;
}
}
// Define the class that is raising events
public class SomeClass
{
// define the event
public event CustomEventHandler CustomEvent;
// method that raises the event - derived classes can override this
protected virtual void OnCustomEvent(CustomEventArgs e)
{
// do some stuff
// ...
// fire the event
if( CustomEvent != null )
CustomEvent(this, e);
}
public void SimulateEvent(int someValue)
{
// raise the event
CustomEventArgs args = new CustomEventArgs(someValue);
OnCustomEvent(args);
}
}
public class Main
{
public static void Main()
{
SomeClass c = new SomeClass();
c.CustomEvent += SomeMethod;
c.SimulateEvent(10); // will cause event
}
public static void SomeMethod(object sender, CustomEventArgs e)
{
Console.WriteLine(e.SomeValue);
}
}
Try putting the line
public delegate void MyFirstDelegate();
inside the Test class.
Also, use the Invoke function on the event instead, i.e.
myFirstDelegate.Invoke();
I wish to create own events and dispatch them.
I never done this before in C#, only in Flex.. I guess there must be a lot of differencies.
Can anyone provide me a good example?
There is a pattern that is used in all library classes. It is recommended for your own classes too, especially for framework/library code. But nobody will stop you when you deviate or skip a few steps.
Here is a schematic based on the simplest event-delegate, System.Eventhandler.
// The delegate type. This one is already defined in the library, in the System namespace
// the `void (object, EventArgs)` signature is also the recommended pattern
public delegate void Eventhandler(object sender, Eventargs args);
// your publishing class
class Foo
{
public event EventHandler Changed; // the Event
protected virtual void OnChanged() // the Trigger method, called to raise the event
{
// make a copy to be more thread-safe
EventHandler handler = Changed;
if (handler != null)
{
// invoke the subscribed event-handler(s)
handler(this, EventArgs.Empty);
}
}
// an example of raising the event
void SomeMethod()
{
if (...) // on some condition
OnChanged(); // raise the event
}
}
And how to use it:
// your subscribing class
class Bar
{
public Bar()
{
Foo f = new Foo();
f.Changed += Foo_Changed; // Subscribe, using the short notation
}
// the handler must conform to the signature
void Foo_Changed(object sender, EventArgs args) // the Handler (reacts)
{
// the things Bar has to do when Foo changes
}
}
And when you have information to pass along:
class MyEventArgs : EventArgs // guideline: derive from EventArgs
{
public string Info { get; set; }
}
class Foo
{
public event EventHandler<MyEventArgs> Changed; // the Event
...
protected virtual void OnChanged(string info) // the Trigger
{
EventHandler handler = Changed; // make a copy to be more thread-safe
if (handler != null)
{
var args = new MyEventArgs(){Info = info}; // this part will vary
handler(this, args);
}
}
}
class Bar
{
void Foo_Changed(object sender, MyEventArgs args) // the Handler
{
string s = args.Info;
...
}
}
Update
Starting with C# 6 the calling code in the 'Trigger' method has become a lot easier, the null test can be shortened with the null-conditional operator ?. without making a copy while keeping thread-safety:
protected virtual void OnChanged(string info) // the Trigger
{
var args = new MyEventArgs{Info = info}; // this part will vary
Changed?.Invoke(this, args);
}
Events in C# use delegates.
public static event EventHandler<EventArgs> myEvent;
static void Main()
{
//add method to be called
myEvent += Handler;
//call all methods that have been added to the event
myEvent(this, EventArgs.Empty);
}
static void Handler(object sender, EventArgs args)
{
Console.WriteLine("Event Handled!");
}
Using the typical .NET event pattern, and assuming you don't need any special arguments in your event. Your typical event and dispatch pattern looks like this.
public class MyClassWithEvents
{
public event EventHandler MyEvent;
protected void OnMyEvent(object sender, EventArgs eventArgs)
{
if (MyEvent != null)
{
MyEvent(sender, eventArgs);
}
}
public void TriggerMyEvent()
{
OnMyEvent(sender, eventArgs);
}
}
Tying something into the event can be as simple as:
public class Program
{
public static void Main(string[] args)
{
MyClassWithEvents obj = new MyClassWithEvents();
obj.MyEvent += obj_myEvent;
}
private static void obj_myEvent(object sender, EventArgs e)
{
//Code called when my event is dispatched.
}
}
Take a look at the links on this MSDN page
Look into 'delegates'.
Define a delegate
Use the delegate type as field/property (adding the 'Event' keyword)
You are now exposing events that users can hook into with "+= MyEventMethod;"
Hope this helps,