Can't seem to get this to work not sure why.
Have this on one of my classes:
public event Action CloseWindowEvent = delegate { };
private void Close()
{
CloseWindowEvent();
}
On another class i'm subscribed:
remarkViewModel.CloseWindowEvent += CloseRequested;
The method never gets called:
private void CloseRequested()
{
dialog.CloseDetailDialog();
}
Thank you.
Can you check the code where the Call to Close() method happens. I dont see any theoretical error in your code. See it works on a simplified model:
It's definitely being called. Here's a snapshot of the event being raised.
In C #, events must be invoked, and in addition, they have two predefined parameters:
object sender and EventArgs e
Here this keyword refers to the object that triggers the event and EventArgs.Empty sends empty arguments to that event, you can also instantiate the class by replacing EventArgs.Empty with new EventArgs
public event EventHandler CloseWindowEvent;
private void CloseEvent()
{
CloseWindowEvent?.Invoke(this, EventArgs.Empty);
}
where
remarkViewModel.CloseWindowEvent += CloseRequested;
private void CloseRequested(object sender, EventArgs e)
{
}
Related
I wanted to ask if this is Event possible in C#. I have not much worked with Events till now.
Say I have a class A which subscribed to a FormClosing Event of a form:
public class A
{
private void f_FormClosed(object sender, FormClosedEventArgs e)
{
//Now here a public Event should be called
}
}
Now there I want a public Event to be called. Let's say now I have another class B which has a certain method.
public class B
{
public void DoSomething()
{
}
}
Now what I want to do:
A Form gets closed so class A is getting notified. There, a public Event gets triggered (which is somewhere in a public class). I want to subscribe my method in class B to this Event so it gets called when that happens. Is this possible? And how is the syntax? I haven't found something useful till now.
Edit: I can't create an instance of class B directly from class A.
Its possible .
Create a new event in A.
Raise the event within the eventhandler f_FormClosed
Subscribe to this event in B.
Within the eventhandler in B call the method DoSomething
For the syntax part you could check MSDN
// A delegate type for hooking up change notifications.
public delegate void ChangedEventHandler(object sender, EventArgs e);
// A class that works just like ArrayList, but sends event
// notifications whenever the list changes.
public class ListWithChangedEvent: ArrayList
{
// An event that clients can use to be notified whenever the
// elements of the list change.
public event ChangedEventHandler Changed;
// Invoke the Changed event; called whenever list changes
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
//you raise the event here.
Changed(this, e);
}
}
Now in your other class do something like this
class EventListener
{
private ListWithChangedEvent List;
public EventListener(ListWithChangedEvent list)
{
List = list;
// Add "ListChanged" to the Changed event on "List".
//This is how we subscribe to the event created in ListWithChangedEvent class
List.Changed += new ChangedEventHandler(ListChanged);
}
// This will be called whenever the list changes.
private void ListChanged(object sender, EventArgs e)
{
Console.WriteLine("This is called when the event fires.");
}
}
I have the following method that is called when ListView item selection is changed:
private void SlideTransitionsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
.........
}
I would like to call this method from some other method. How would I do that?
That is an event handler. It's fired on UI actions. Calling it directly isn't a great idea. Put a method inside it, and then you can call that method if you need to from other places.
private void SlideTransitionsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DoSomeStuffOnSelectionChanged();
}
public void DoSomeStuffOnSelectionChanged()
{
// enter code here
}
Extract all code from SlideTransitionsList_SelectionChanged handler to other method and call it.
private void SlideTransitionsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DoSmth();
}
...
private void OtherMethod()
{
DoSmth();
}
If the paramters of sender and e are not used, simply call the method directly from any other method.
SlideTransitionsList_SelectionChanged(null, null);
Note that you are not firing off an event by calling this method; this is just the event's callback method and can be used by any other method.
The advice given in the other answers are just as correct, but are simply syntatic suger for coding paradigms and can be used as preference or styles are dictated.
I've seen many developers when wanting to invoke an Event they assign it to a local variable named handler and invoke handler instead of invoking Event directly.
Why we are not invoking Events directly?
private void OnSomethingChanged(EventArgs e)
{
if (SomethingEvent != null)
{
SomethingEvent(this, e);
}
}
The code you've posted isn't thread-safe, basically. If the final subscriber unsubscribes in a different thread after the if check but before the invocation, you'll get a NullReferenceException.
One option is to write an extension method:
public static void NullSafeInvoke(this EventHandler handler,
object sender, EventArgs e)
{
if (handler != null)
{
handler(this, e);
}
}
You can then write:
private void OnSomethingChanged(EventArgs e)
{
SomethingEvent.NullSafeInvoke(this, e);
}
You'd probably want another overload for EventHandler<T>, too.
There is a possibility of a race condition if the event is not copied (relevant to multi-threaded applications only).
If one thread unsubscribes from the event just after the null check leaving nothing subscribed to it, you will get a NullReferenceException.
I also don't understand why. There is a simple and pretty safe method:
// when constructing of instance, to create empty subscription
public event EventHandler SomethingEvent = delegate { };
private void OnSomethingChanged(EventArgs e)
{
// and call it directly
SomethingEvent(this, e);
}
I am still trying to learn about c#, my question is how would I pass a variable from Item1_Click to Item2_Click, is this the same thing as passing them between methods or is this different because they are event handlers?
public partial class Events : System.Web.UI.UserControl
{
protected void Item1_Click(object sender, EventArgs e)
{
//code
}
protected void Item2_Click(object sender, EventArgs e)
{
//code
}
}
They are still regular methods, so you're still able to call them the same way you normally would.
protected void Item1_Click(object sender, EventArgs e)
{
// Call the event handler for Item2, passing the arguments
// Item1 received
Item2_Click(sender, e);
}
protected void Item2_Click(object sender, EventArgs e)
{
// Make it happen.
}
If you want to re-use Item1_Click just bind the click event of the other object to Item1_Click as well.
See the links below for some more information on events in C#.
MSDN Event Tutorial
MSDN C# Programming Guide (Events)
Event handlers are called by the publisher of the event. So you'd need to cache the value in a member variable if both handlers are in the same type. Item1 click caches something (e.g. the selection in a variable) and Item2 click uses this member variable for its own handling.
However nothing stops you from calling the event-handler#2 from event-handler#1 ; since it is a method after all. In this case, you could slot in the parameter in the EventHandler argument but it is a bit non-intuitive.
What you've shown above, is a method. It's just that I imagine you've subscribed your methods to events on a couple of buttons.
It is then up to the buttons to populate the EventArgs instances themselves. If you wish to alter what goes into an EventArgs then you'd need to inherit from a Button and override the OnClick method to fire the event manually.
You could have some state information on your form (if you want shared information between the two methods). Or if you're literally wanting to pass information from Item1_Click to Item2_click then you can just call:
protected void Item1_Click(object sender, EventArgs e)
{
this.Item2_Click(sender new EventArgs()); // <== Stick information in EventArgs
}
If you want to preserve some value from a first click you can set a variable and read it from your other handler.
public partial class Events : System.Web.UI.UserControl
{
private SomeType variable;
protected void Item1_Click(object sender, EventArgs e)
{
variable = someValue;
//code
}
protected void Item2_Click(object sender, EventArgs e)
{
//code + do stuff with variable
}
}
Event handlers are methods themselves, so no difference there. Sending data (variables if you will) between methods is done through parameters, however, Event handlers are required to have a specific signature, so you can't just add more parameters. The way to go here is to use a class member (field or property) as some sort of "global variable" (global to the class) as mentioned in #Zebi's answer
Hope this helps :)
An event handler is just a method, that is called in some specific scenario. There's nothing to prevent you from explicitlly calling those methods, so
protected void Item1_Click(object sender, EventArgs e)
{
Item2_Click(sender, e); //pass the original arguments
Item2_Click(null, null); //pass some other arguments
Item1_Click(null, null); //recursively call the handler.
}
is perfectly valid C# code. However, it's a bad practice to use event handler for anything else than, basically handling the event. If two handlers need to use some same logic, it's better to do:
protected void Item1_Click(object sender, EventArgs e)
{
CommonLogic();
}
protected void Item2_Click(object sender, EventArgs e)
{
CommonLogic();
}
private void CommonLogic()
{
//the common logic goes here
}
Instead of calling your event handler directly, you might want to create methods that wrap the functionality of Item1_Click and Item2_Click. For example..
public partial class Events : System.Web.UI.UserControl
{
protected void Item1_Click(object sender, EventArgs e)
{
var theParam = GetParamValue();
//code
Item1Method(theParam);
}
protected void Item2_Click(object sender, EventArgs e)
{
Item2Method();
}
private void Item1Method(object param1)
{
// Item 1 code goes here...
}
private void Item2Method()
{
//item 2 code goes here...
// then call Item1Method
var param2 = GetParamValue();
Item1Method(param2);
}
}
This is just an example of how to avoid calling your event handlers. Doing this will make your code more maintainable down the road.
In addition, now you don't have to worry about providing a sender and Event Args as parameters when trying to run the functionality in Item1_Click
Let's say I have an event. Let's call it DoStuff. Before DoStuff happens, I'm trying to use another event, PreviewDoStuff, to check if I need to prevent DoStuff from being called. The problem I'm facing with this is that I'm unable to get any kind of value back from the PreviewDoStuff, like a return code or anything due to how events are written. And event args aren't passed back to the caller, so I can't get the event args "handled" property. I'm sure there has to be a way to do it, but I'm not sure how. Any ideas?
Thanks!
Declare the event as EventHandler<CancelEventArgs>. Then the listener can set Cancel to true, and you can use that value to determine whether to raise the "real" event or not.
Mandatory code sample:
public event EventHandler<CancelEventArgs> PreviewDoStuff;
public event EventHandler DoStuff;
private void RaiseDoStuff()
{
CancelEventArgs args = new CancelEventArgs();
OnPreviewDoStuff(args);
if (!args.Cancel)
{
OnDoStuff(EventArgs.Empty);
}
}
protected void OnPreviewDoStuff(CancelEventArgs e)
{
EventHandler<CancelEventArgs> previewDoStuff = PreviewDoStuff;
if (previewDoStuff != null)
{
previewDoStuff(this, e);
}
}
protected void OnDoStuff(EventArgs e)
{
EventHandler doStuff = DoStuff;
if (doStuff != null)
{
doStuff(this, e);
}
}
For an example of this in real-life use, check the FormClosing event, which uses a FormClosingEventArgs class, which in turn inherits from CancelEventArgs.
Have your PreviewDoStuff set an internal flag which DoStuff checks when it fires. Even better, have the code that raises DoStuff check the flag before it raises the event.
I assume you mean you want to create your own event called DoStuff. I think it's possible to pass "ref" arguments:
public delegate void PreviewDoStuffFunc(ref bool Handled);
public event PreviewDoStuffFunc PreviewDoStuff;
But the standard way would be to use something like CancelEventArgs:
public event CancelEventArgs PreviewDoStuff;
public event EventArgs DoStuff;
Then after you fire the preview event, you check the Cancel:
var e = new CancelEventArgs();
if (PreviewDoStuff != null)
PreviewDoStuff(this, e);
if (!e.Cancel)
DoStuff(this, EventArgs.Empty);