WinForm event subscription to another class - c#

public partial class Form1 : Form
{
private EventThrower _Thrower;
public Form1()
{
InitializeComponent();
}
private void DoSomething()
{
MessageBox.Show("It worked");
}
private void button1_Click(object sender, EventArgs e)
{
_Thrower = new EventThrower();
//using lambda expression..need to use .NET2 so can't use this.
_Thrower.ThrowEvent += (sender2, args) => { DoSomething(); };
var eventThrower = new EventThrower();
eventThrower.test();
}
}
public class EventThrower
{
public delegate void EventHandler(object sender, EventArgs args);
public event EventHandler ThrowEvent = delegate { };
public void SomethingHappened()
{
ThrowEvent(this, new EventArgs());
}
public void test()
{
System.Threading.Thread.Sleep(1000);
SomethingHappened();
}
}
I'm trying to get my winform UI to subscribe to an event in EventThrower class. DoSomething never fires.
How to subscribe to other class' events in c#?

The event is not static, one instance of the EventHandler exists for each instance of EventThrower.
You subscribe to the event on _Thrower, yet you create a new instance of EventThrower and call test() on that instance. You never subscribed to the event on that instance, so your handler doesn't run.
It should be:
_Thrower.ThrowEvent += (sender2, args) => { DoSomething(); };
_Thrower.test();

This is because you create a new EventThrower before calling test.
If you change:
var eventThrower = new EventThrower();
eventThrower.test();
to:
_Thrower.test();
It will call DoSomething.

Related

Create EventHandler and listen to Event from another class

I've created event as bellow and want to listen to it and execute method in another class when it fires
but saveEvent always comes to be null and it doesn't fire
I don't know what I've missed
here's my first class has button
internal partial class OpenSaveReportWizardForm : Form
{
public event EventHandler saveEvent;
private void saveButton_Click(object sender, EventArgs e)
{
saveEvent?.Invoke(this, e);
}
}
and here's the second class where I want to listen to saveEvent
internal class Database
{
public Database()
{
Program._wizardForm.saveEvent += (sender, e) => HandleSaveMethod( );
}
public void HandleSaveMethod()
{
// do something
}
here's where I open the form
internal class Program
{
public static OpenSaveReportWizardForm _wizardForm;
private static void Main()
{
OpenFileCommandHandler();
}
void OpenFileCommandHandler()
{
_wizardForm = new OpenSaveReportWizardForm( );
_wizardForm.ShowDialog();
}
}
Because you disposed wizardForm, after that event is cleared.
You should write next code:
internal class Database
{
private bool _isDisposed;
private OpenSaveReportWizardForm _wizardForm;
public Database()
{
_wizardForm = new OpenSaveReportWizardForm(m_Opening,m_ConnectionProperties,m_ColumnProperties))
_wizardForm.saveEvent += (sender, e) => HandleSaveMethod( );
}
public void HandleSaveMethod()
{
// do something
}
public void Dispose()
{
if(_isDisposed)
return;
_isDisposed = true;
_wizardForm.saveEvent -= HandleSaveMethod;
_wizardForm.Dispose();
}

How do I correctly close a winform if I have used invoke to update the form from another thread

I have a winform that subscribes to events from a callback interface. I use...
public partial class Form1 : Form
{
MyTestCallBack _callback;
public Form1()
{
InitializeComponent();
//Start otherthread
API.Create()
_callback = new MyTestCallBack();
_callback.MyTestCallBackEvent += callback_MyTestCallBackEvent;
_callback.OnUpdate();
}
private callback_MyTestCallBackEvent(MyTestCallBackEventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action(() =>
{
callback_MyTestCallBackEvent(sender, e);
}));
return;
}
label1.Text = e.SomeObject.GetDisplayString();
} }
class MyTestCallBackEventArgs : EventArgs {
public SomeObject SomeObj { get; set; } }
class MyTestCallBack : Callback {
public event EventHandler<MyTestCallBackEventArgs> MyTestCallBackEvent;
protected virtual void OnMyTestCallBackEvent(MyTestCallBackEventArgs e)
{
if (MyTestCallBackEvent != null)
MyTestCallBackEvent(this, e);
}
public void OnUpdate(SomeObject someobj)
{
OnMyTestCallBackEvent(new MyTestCallBackEventArgs { SomeObject = someobj });
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//tried this but still crashes
_callback.MyTestCallBackEvent -= callback_MyTestCallBackEvent;
API.Destroy()
}
When I try to shutdown my form it crashes. "Freezes". I assume it is because of the other thread not shuting down correctly.
How do safely unsubscribe from this event so that I can close down correctly.
To immediately unsubscribe from the event, use:
_callback.MyTestCallBackEvent -= callback_MyTestCallBackEvent;

How to access the event handler in another class

I have a click event handler in class A with some logic. And now i want to access class A event handler from class B and do some logic so that class B event hadler logic fires first followed by class A event handler.
Example:
Class A
private void calculate_Click(object sender, System.EventArgs e)
{ this.MyMethod(); }
Class B
private void calculate_Click(object sender, System.EventArgs e)
{ // My new code.. (This should trigger first) this.MyMethod(); }
You may use event exposed by class A and consumed by class B like we do with Button class. Button exposes click event and in our form class we subscribe for click event being exposed by Button class.
I found this simple example for understanding here
using System;
namespace wildert
{
public class Metronome
{
public event TickHandler Tick;
public EventArgs e = null;
public delegate void TickHandler(Metronome m, EventArgs e);
public void Start()
{
// while (true) //uncomment this line if you want event to fire repeatedly
{
System.Threading.Thread.Sleep(3000);
if (Tick != null)
{
Tick(this, e);
}
}
}
}
public class Listener
{
public void Subscribe(Metronome m)
{
m.Tick += new Metronome.TickHandler(HeardIt);
}
private void HeardIt(Metronome m, EventArgs e)
{
System.Console.WriteLine("HEARD IT");
}
}
class Test
{
static void Main()
{
Metronome m = new Metronome();
Listener l = new Listener();
l.Subscribe(m);
m.Start();
}
}
}
Assuming class B has instance member A instanceOfClassA initilized properly with an instance of A:
private void calculate_Click(object sender, System.EventArgs e)
{
// My new code.. (This should trigger first)
instanceOfClassA.MyMethod();
// other code
}
You may also consider inheriting class B from A:
class B:A
{
private void calculate_Click(object sender, System.EventArgs e)
{
// My new code.. (This should trigger first)
this.MyMethod(); // will come from base class A implementation.
// other code
}
}

WinForm events in another class .NET2 Simplify delegate

Any way to make this working code simpler ie the delegate { }?
public partial class Form1 : Form
{
private CodeDevice codeDevice;
public Form1()
{
InitializeComponent();
codeDevice = new CodeDevice();
//subscribe to CodeDevice.ConnectionSuccessEvent and call Form1.SetupDeviceForConnectionSuccessSate when it fires
codeDevice.ConnectionSuccessEvent += new EventHandler(SetupDeviceForConnectionSuccessState);
}
private void SetupDeviceForConnectionSuccessState(object sender, EventArgs args)
{
MessageBox.Show("It worked");
}
private void button1_Click(object sender, EventArgs e)
{
codeDevice.test();
}
}
public class CodeDevice
{
public event EventHandler ConnectionSuccessEvent = delegate { };
public void ConnectionSuccess()
{
ConnectionSuccessEvent(this, new EventArgs());
}
public void test()
{
System.Threading.Thread.Sleep(1000);
ConnectionSuccess();
}
}
WinForm event subscription to another class
How to subscribe to other class' events in c#?
If don't think you could simplyfy:
public event EventHandler ConnectionSuccessEvent = delegate { }
even in c#3 + you could only do
public event EventHandler ConnectionSuccessEvent = () => { }
However you could simplify
codeDevice.ConnectionSuccessEvent += new EventHandler(SetupDeviceForConnectionSuccessState);
to
codeDevice.ConnectionSuccessEvent += SetupDeviceForConnectionSuccessState;

call event from form2 in form1

hi
call event from form2 in form1?
for example :
The following code into form2 :
private void Form2_Load(object sender, EventArgs e)
{
MessageBox.Show("http://stackoverflow.com");
}
What to write in a form1?
Why are you wanting to call the event? Will you know the sender and the Event Args?
Why don't you just create a public method in Form2 that Form1 is able to see?
how about form2.Form2_Load(this, null)
You can't call private members of a class from outside it.
You can change the accessibility to internal, which will make it visible within the assembly - if your form1 is in the same assembly.
Alternatively you can make it a public method, which would make it globally accessible.
However, you shouldn't call event handlers in such a manner - they are supposed to handle events that the declaring class raises.
For the sample code you gave, a better solution would be to create a public or internal method that can be called from this event handler:
private void Form2_Load(object sender, EventArgs e)
{
MyMethod();
}
public MyMethod()
{
MessageBox.Show("http://stackoverflow.com");
}
In order to call this method from form1, it needs to know about form2:
// in form1
Form frm2 = new Form2();
frm2.MyMethod();
You can't raise an Event from outside a class.
The convention is that you call a OnEventname method in the class. Usually this method is protected (can't only accessed from the class itself or others that inherit from it)
// in form1
private void Method1()
{
using (var form2 = new Form2())
{
form2.Show();
form2.RaiseLoadEvent(EventArgs.Empty);
}
}
// Create this method in form2
public void RaiseLoadEvent(EventArgs e)
{
OnLoad(this, e);
}
// The OnLoad method already exists in form 2
// But it usually looks like this
protected void OnLoad(EventArgs e)
{
var eh = LoadEventHandler;
if (eh != null)
{
eh(this, e);
}
}
But I don't suggest to raise the LoadEvent, because It is raised only once after the creation of the form. More usual is to react to the Load event to modify the form.
privat void Method1()
{
using (var form2 = new Form2())
{
// Add Event Handler
form2.Load += new EventHandler(form2_Load);
form2.ShowDialog();
}
// Allways remove Event Handler to avoid memory leaks
form2.Load -= new EventHandler(form2_Load);
}
private void form2_Load(object sender, EventArgs e)
{
form2.Text = "Hello from form1";
}
Form1 (the event publisher) should expose a separate, public event property for Form2 (the subscriber) to subscribe to.
For example: the form publishing the event will look like this:
public partial class Publisher : Form
{
public event PostUpdateHandler OnPostUpdate;
public Publisher()
{
InitializeComponent();
new Subscriber(this).Show();
}
private void button1_Click(object sender, EventArgs e)
{
if (OnPostUpdate != null)
{
OnPostUpdate(new PostUpdateArgs(textBox1.Text));
}
}
}
public delegate void PostUpdateHandler(PostUpdateArgs args);
public class PostUpdateArgs : EventArgs
{
public string UpdateText;
public PostUpdateArgs(string s)
{
UpdateText = s;
}
}
The subscribing form looks like this:
public partial class Subscriber : Form
{
public Subscriber()
{
InitializeComponent();
}
public Subscriber(Publisher publisher) : this()
{
publisher.OnPostUpdate += new PostUpdateHandler(publisher_OnPostUpdate);
}
private void publisher_OnPostUpdate(PostUpdateArgs args)
{
this.Form2_Load(null, null);
}
private void Subscriber_FormClosed(object sender, FormClosedEventArgs e)
{
this.Dispose();
}
private void Form2_Load(object sender, EventArgs e)
{
MessageBox.Show("http://stackoverflow.com");
}
}
When the user presses button1 on the publishing form, the subscribing form will execute the code associated with the delegate, resulting in a message box popping up with the message http://stackoverflow.com.

Categories