I don't know how can I break event handler method list. For example I have follow code. What should i write in IF statement?
public event EventHandler myEvent;
...
myEvent += new EventHandler(met1);
myEvent += new EventHandler(met2);
myEvent += new EventHandler(met3);
...
public void met2(object sender, EventArgs e)
{
...
if(myCondition)
{
//there I want to break execution of all methods assiciated with myEvent event
//I want to break met2 and don't allow to execute met3
}
...
}
You can define your delegate, so your custom event handler, whith its custom EventArgs, with boolean value.
Example:
public class MyEventArg : EventArgs {
public bool Handle {get;set;}
}
myEvent += new MyEventHandler(met1);
public void met2(object sender, MyEventArgs e)
{
if(e.Handled)
return;
if(myCondition)
{
e.Handled = true;
return;
}
...
}
In this way, if we in any other event handlder before processing it, check if Handled == true, one time it's set into that state from one of them, others would skip that event processing.
Just an idea example, you have to change it to fit your code exact needs.
Look into KeyDownEventArgs, there is an Property Handled wich can be set to true.
You could do something similar:
class myClass {
public event EventHandler myEvent;
myEvent += new EventHandler(met1);
myEvent += new EventHandler(met2);
myEvent += new EventHandler(met3);
public void metN(object sender, MyCustomEventArgs e)
{
if(e.Cancel)
return;
// Do whatever you like
if(<someBooleanStatement>)
{
e.Cancel = true;
return;
}
// Do whatever you like
}
}
Related
I can't figure out how to do this, heres sample code. Of what I wish to do.
public Class MainForm : Form
{
MyUserControl MyControl = new MyUserControl;
private void Button_Click(object sender, EventArgs e)
{
//Create MyEvent
}
}
public Class MyUserControl : UserControl
{
//listen for MyEvent from MainForm, and perform MyMethod
public void MyMethod()
{
//Do Stuff here
}
}
Step 1) Expose an event on MainForm... say..
public event Action simpleEvent
Step 2) Give MyUserControl a constructor that takes an instance of MainForm and bind an action to that event
public MyUserControl(MainForm form) {
form += () => Console.WriteLine("We're doing something!")
}
Step 3) raise the event in MainForm.Button_Click
if(simpleEvent != null) simpleEvent();
Note: You could register your own delegates and work with something other than lambda expressions. See http://msdn.microsoft.com/en-us/library/17sde2xt.aspx for a more thorough explanation
Your end result would look like...
public Class MainForm : Form
{
public event Action MyEvent;
MyUserControl MyControl = new MyUserControl(this);
private void Button_Click(object sender, EventArgs e)
{
if(simpleEvent != null) simpleEvent();
}
}
public Class MyUserControl : UserControl
{
//listen for MyEvent from MainForm, and perform MyMethod
public MyUserControl(MainForm form) {
simpleEvent += () => MyMethod();
}
public void MyMethod()
{
//Do Stuff here
}
}
This is how to delegate to an event of a private member, so the outside can listen to it.
public event EventHandlerType EventHandlerName
{
add
{
this._privateControl.EventHandlerName += value;
}
remove
{
this._privateControl.EventHandlerName -= value;
}
}
Another option would be to have an event in your form class:
public event EventHandler MyEvent;
And listen to the private member's event:
this._customControl.SomeEvent += this.SomeEventHandler;
With this:
private void SomeEventHandler(object sender, EventArgs e)
{
if (this.MyEvent != null)
{
this.MyEvent(this, e);
}
}
The usage from the outside in both cases will be the same:
var form = new Form1();
form1.MyEvent += (o, e) => { Console.WriteLine("Event called!"); };
The bottom line is the you must implement functionality inside your form to allow the outside subscribe/listen to inner events.
//listen for MyEvent from MainForm, and perform MyMethod
That's the wrong way around. Publishing an event in control is useful, the control cannot possibly guess how it is going to get used. It however most certainly should not know anything about an event that may or may not be available in the form that it gets dropped on. That has the nasty habit of blowing up when the form just doesn't (yet) have the event. The bad kind too, a crash at design time that puts up the White Screen of Darn and prevents you from fixing the problem.
A form doesn't have to guess, it knows exactly what controls it has. So where ever in the form you might want to raise the event, just call the control's MyMethod method directly. And if that's wrong for some reason, like removing the control but not the call, then you just get a compile error that's easy to fix.
I have a winform application that goes with name myForm. Within this form I open another form:
private OtherForm otherForm; //this is a field
private OpenOtherForm()
{
if (otherForm == null)
{
otherForm = new OtherForm();
otherForm.FormClosing += delegate { MessageBox.Show("OtherForm will be closed"); otherForm = null};
}
MessageBox.Show("Form is already active!");
}
This works fine. But I have some methods in the second form as well. I would like to try capturing theire call.
For example if OtherForm.DoSomething() is called within the second form, I want a message box to show thi.
I tried to assign OtherForm.DoSomething() += delegate { /* mesagebox */}; But this does not compile
otherForm.FormClosing += delegate { .. } is compiling because FormClosing is of type Event. An event can be subscribed to and when it's fired your code will run.
You can't use this syntax on a method like DoSomething(). A method can only be called with something like otherForm.DoSomething(). The code in DoSomething() will then be executed.
What you can do however is create your own event and fire it when DoSomething() is executed in the second form.
Here is the MSDN Documentation on publishing your own Event.
It would be something like:
public event EventHandler RaiseCustomEvent;
public void DoSomething()
{
OnRaiseCustomEvent();
}
protected virtual void OnRaiseCustomEvent()
{
EventHandler handler = RaiseCustomEvent;
if (handler != null)
{
handler(this, EventArgs.Empty););
}
}
If you want to respond to a call in another form you could add an event to the other form and raise it in the method you are trying to respond to.
class Form1: Form
{
public void Button1_Click(object sender, EventArgs e)
{
var form2 = new Form2();
form2.SomeMethodCalled += Form2_SomeMethodCalled;
}
public void Form2_SomeMethodCalled(object sender, EventArgs e)
{
// method in form2 called
}
}
class Form2 : Form
{
public event EventHandler SomeMethodCalled;
public void SomeMethod()
{
OnSomeMethodCalled();
// .....
}
private void OnSomeMethodCalled()
{
var s = SomeMethodCalled;
if(s != null)
{
s(this, EventArgs.Empty);
}
}
}
I am using an API that has the following EventHandler:
static EventHandler<GPRSArgs> EventStateChanged
How can I receive these events in my client application so that I can react to them?
subscribe to the event.
lambda:
EventStateChanged += (sender, gprsArgs) => { do your thing }
delegate:
void Listener(object sender, GPRSArgs args)
{
do your thing
}
EventStateChanged += Listener;
just hook into this event. You gave few code but assuming your class name is MyClass you can do
MyClass.EventStateChanged += MyEventHandler
with
void MyEventHandler(object sender, GRPSArgs e)
{
// ...
}
or hooking up with a lambda:
MyClass.EventStateChanged += (sender, e) => { /* whatever you want */ }
Subscribe to it, as you would any other event.
I assume APIClass is the class the API has with the EventStateChanged event.
Somewhere in your code you subscribe to the event as below:
APIClass.EventStateChanged += EventStateChangedHandler;
This assumes you have a method as follows:
private void EventStateChangedHandler(object sender, GPRSArgs e)
{
// Code to react to the event.
}
You could do this in one line, with a lambda:
APIClass.EventStateChanged += (sender, e) => { /* Code to react to the event */ }
I assume you left out a public and an event in the declaration:
public class GPRSThingy
{
public static event EventHandler< GPRSArgs > EventStateChanged;
...
}
Then use it
void DoSomething(GPRSArgs e)
{
// whatever
}
var gprstThingy = new GPRSThingy();
gprstThingy.EventStateChanged += (sender, e) => { DoSomething(e); };
Sort of.
You will need to subscribe to the event:
theClassWithEvent.EventStateChanged +=
delegate (object sender, GRPSArgs e)
{
//process the event
};
The event will also need to be called to alert all subscribers, from within theClassWithEvent:
if (EventStateChanged != null)
{
EventStateChanged(someObject, new GRPSArgs());
}
Note the use of someObject above, because the exposed event is static you can't pass this and the sender, therefore will need to send something apt. Though, since you say you're using this from an API, I think we can assume that you don't need to make this call and should only subscribe to the event.
A simple scenario: a custom class that raises an event. I wish to consume this event inside a form and react to it.
How do I do that?
Note that the form and custom class are separate classes.
public class EventThrower
{
public delegate void EventHandler(object sender, EventArgs args) ;
public event EventHandler ThrowEvent = delegate{};
public void SomethingHappened() => ThrowEvent(this, new EventArgs());
}
public class EventSubscriber
{
private EventThrower _Thrower;
public EventSubscriber()
{
_Thrower = new EventThrower();
// using lambda expression..could use method like other answers on here
_Thrower.ThrowEvent += (sender, args) => { DoSomething(); };
}
private void DoSomething()
{
// Handle event.....
}
}
Inside your form:
private void SubscribeToEvent(OtherClass theInstance) => theInstance.SomeEvent += this.MyEventHandler;
private void MyEventHandler(object sender, EventArgs args)
{
// Do something on the event
}
You just subscribe to the event on the other class the same way you would to an event in your form. The three important things to remember:
You need to make sure your method (event handler) has the appropriate declaration to match up with the delegate type of the event on the other class.
The event on the other class needs to be visible to you (ie: public or internal).
Subscribe on a valid instance of the class, not the class itself.
Assuming your event is handled by EventHandler, this code works:
protected void Page_Load(object sender, EventArgs e)
{
var myObj = new MyClass();
myObj.MyEvent += new EventHandler(this.HandleCustomEvent);
}
private void HandleCustomEvent(object sender, EventArgs e)
{
// handle the event
}
If your "custom event" requires some other signature to handle, you'll need to use that one instead.
Similar to the KeyPress events, I want whoever is subscribed to the event to be able to set e.Handled in my EventArgs class. If they return true, I no longer want to continue firing events. Any ideas how to implement this? Right now, here is my method:
protected void OnDataReceived(SocketAsyncEventArgs e)
{
if (DataReceived != null)
{
DataReceived(this, e);
}
}
From my understanding, everybody who is subscribed to the event will receive notification, so setting e.Handled = true; will have no effect here.
Sample code for a solution using Delegate.GetInvocationList:
public class MyEventArgs : EventArgs
{
public bool Handled { get; set; }
}
public class SomeClass
{
public event EventHandler<MyEventArgs> SomeEvent;
protected virtual void OnSomeEvent(MyEventArgs e)
{
var listeners = SomeEvent.GetInvocationList();
foreach (var listener in listeners)
{
if (e.Handled) break;
((EventHandler<MyEventArgs>)listener).Invoke(this, e);
}
}
}