I would like to create an event handler [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Create event handler for OnScroll for web browser control
I would like to create an event handler for a web browser control scrolling.
webCompareSQL.Document.Window.Scroll
Can some one show me how to create an event handler?

In the class you add a delegate and an event, and usually a simple internal method that checks for null and calls the event:
public delegate void ScrollHandler();
public event ScrollHandler Scrolled;
internal void OnScrolled()
{
if (this.Scrolled != null)
this.Scrolled();
}
Then in the actual code you would register a method for the event using:
MyClass.Scrolled += new ScrollHandler(MyMethod);
void MyMethod()
{
Console.WriteLine("It was scrolled.");
}

Related

Since we have multicast delegates, why do we need events? [duplicate]

This question already has answers here:
Difference between events and delegates and its respective applications [closed]
(10 answers)
Closed 3 years ago.
I was asked this question in an interview, and either I'm suffering from brain-lock or just plain dumb, but I didn't have an answer.
Couple of reasons why we need events:
Restricting scope, you do not want to expose your events, like you can for your delegates.
You can have events as fields in your interfaces and not delegates
Example below:
Class Printer
{
public event EventHandler Print;
public void Start()
{
OnPrint();
}
protected virtual void OnPrint()
{
Print?.Invoke(this,EventArgs.Empty);
}
}
class Program
{
static void Main(string[] args)
{
//When Print is an EventHander
var printer = new Printer();
printer.Print += PrintEvent;
printer.Start();
//If Print was a delegate this is possible, else you get compile time errors
printer.Print(null,null); // Events will not allow to have a direct invoke
printer.Print = null; //You cannot assign a null to an Event Handler
}
private static void PrintEvent(object sender, EventArgs e)
{
System.Console.WriteLine("Printing event");
}
}

Event being declared as Delegate [duplicate]

This question already has answers here:
Event declaration with assignment to empty delegate
(2 answers)
Closed 4 years ago.
While going through C# example codes, I have found this declaration:
public event myEventHandler myEvent = delegate { };
What does this statement mean? It is not inline with other declarations of delegate I have seen on internet.
public event myEventHandler myEvent = delegate { };
Assigns an function to the event when an instance of the class is created by simply delegating it with anonymous function.
When assigning a function to event's invocation list, the following notation is used
myClass.myEvent += delegate { };
However the following assignment is also valid inside the parent class, but it basically discards all the existing invocation list unless it is used in ctor.
myEvent = delegate {};

What is the difference between these two event declarations? [duplicate]

This question already has answers here:
What are the differences between delegates and events?
(11 answers)
Closed 6 years ago.
I have two events in a class
public event AcquiredDataEvent OnNewAcquiredData;
public delegate void AcquiredDataEvent(int[] newData);
public ScanStartedEvent ScanStarted;
public delegate void ScanStartedEvent();
I just realized that ScanStarted does not have the keyword event before it. Most likely the result of a typo by me, though it still works as expected.
What is the difference between the two events if any?
ScanStarted is not event. It's just a field of delegate type.
It can be invoked outside of class where field is declated.
It does not provide add/remove methods (that is what event is, like property is a pair of get/set methods) for attaching/removing event handlers - you can simply assign new delegate to ScanStarted field.
BTW Just like you can have property without backing field
public int Value
{
get { return 42; }
set { Console.WriteLine($"Haha, keep {value} for yourself"); }
}
You can have event without delegate field under the hood
public event AcquiredDataEvent OnNewAcquiredData
{
add { Console.WriteLine("Trying to attach some handlers?"); }
remove { Console.WriteLine("Haha, you should attach something first!"); }
}

Get delegate handler from event [duplicate]

This question already has answers here:
Is it possible to "steal" an event handler from one control and give it to another?
(4 answers)
Closed 7 years ago.
I am trying to get the event handler without doing any changes in MyControl class. I tried to use reflection but I am not able to get the handler.
Following is a code sample.
Thanks
public class MyControl : Control
{
public void Register()
{
SizeChanged += MyControl_SizeChanged;
}
void MyControl_SizeChanged(object sender, EventArgs e)
{
// Do something
}
}
//[TestFixture]
public class MyControlTest
{
// [Test]
public void RegisterTest()
{
var control = new MyControl();
control.Register();
var eventInfo = control.GetType().GetEvent("SizeChanged", BindingFlags.Public | BindingFlags.Instance);
// Need to get the handler (delegate) and GetInvocationList().Count
EventHandler handler = ...;
var count = handler.GetInvocationList().Count();
Assert.That(count, IsolationLevel.EqualTo(1));
}
}
Events don't actually have handlers; an event is just a pair of specially-named add & remove methods.
For more information, see my blog.
How the event stores its handlers is an implementation detail; WinForms controls use an EventHandlerList.
You can see this in the source.
That's probably because of it's protection level which is currently private as can be seen from your posted code
void MyControl_SizeChanged(object sender, EventArgs e)
{
// Do something
}

C# pattern to prevent an event handler hooked twice [duplicate]

This question already has answers here:
How to ensure an event is only subscribed to once
(8 answers)
Closed 8 years ago.
Duplicate of: How to ensure an event is only subscribed to once
and Has an event handler already been added?
I have a singleton that provides some service and my classes hook into some events on it, sometimes a class is hooking twice to the event and then gets called twice.
I'm looking for a classical way to prevent this from happening. somehow I need to check if I've already hooked to this event...
How about just removing the event first with -= , if it is not found an exception is not thrown
/// -= Removes the event if it has been already added, this prevents multiple firing of the event
((System.Windows.Forms.WebBrowser)sender).Document.Click -= new System.Windows.Forms.HtmlElementEventHandler(testii);
((System.Windows.Forms.WebBrowser)sender).Document.Click += new System.Windows.Forms.HtmlElementEventHandler(testii);
Explicitly implement the event and check the invocation list. You'll also need to check for null:
using System.Linq; // Required for the .Contains call below:
...
private EventHandler foo;
public event EventHandler Foo
{
add
{
if (foo == null || !foo.GetInvocationList().Contains(value))
{
foo += value;
}
}
remove
{
foo -= value;
}
}
Using the code above, if a caller subscribes to the event multiple times, it will simply be ignored.
I've tested each solution and the best one (considering performance) is:
private EventHandler _foo;
public event EventHandler Foo {
add {
_foo -= value;
_foo += value;
}
remove {
_foo -= value;
}
}
No Linq using required. No need to check for null before cancelling a subscription (see MS EventHandler for details). No need to remember to do the unsubscription everywhere.
You really should handle this at the sink level and not the source level. That is, don't prescribe event handler logic at the event source - leave that to the handlers (the sinks) themselves.
As the developer of a service, who are you to say that sinks can only register once? What if they want to register twice for some reason? And if you are trying to correct bugs in the sinks by modifying the source, it's again a good reason for correcting these issues at the sink-level.
I'm sure you have your reasons; an event source for which duplicate sinks are illegal is not unfathomable. But perhaps you should consider an alternate architecture that leaves the semantics of an event intact.
You need to implement the add and remove accessors on the event, and then check the target list of the delegate, or store the targets in a list.
In the add method, you can use the Delegate.GetInvocationList method to obtain a list of the targets already added to the delegate.
Since delegates are defined to compare equal if they're linked to the same method on the same target object, you could probably run through that list and compare, and if you find none that compares equal, you add the new one.
Here's sample code, compile as console application:
using System;
using System.Linq;
namespace DemoApp
{
public class TestClass
{
private EventHandler _Test;
public event EventHandler Test
{
add
{
if (_Test == null || !_Test.GetInvocationList().Contains(value))
_Test += value;
}
remove
{
_Test -= value;
}
}
public void OnTest()
{
if (_Test != null)
_Test(this, EventArgs.Empty);
}
}
class Program
{
static void Main()
{
TestClass tc = new TestClass();
tc.Test += tc_Test;
tc.Test += tc_Test;
tc.OnTest();
Console.In.ReadLine();
}
static void tc_Test(object sender, EventArgs e)
{
Console.Out.WriteLine("tc_Test called");
}
}
}
Output:
tc_Test called
(ie. only once)
Microsoft's Reactive Extensions (Rx) framework can also be used to do "subscribe only once".
Given a mouse event foo.Clicked, here's how to subscribe and receive only a single invocation:
Observable.FromEvent<MouseEventArgs>(foo, nameof(foo.Clicked))
.Take(1)
.Subscribe(MyHandler);
...
private void MyHandler(IEvent<MouseEventArgs> eventInfo)
{
// This will be called just once!
var sender = eventInfo.Sender;
var args = eventInfo.EventArgs;
}
In addition to providing "subscribe once" functionality, the RX approach offers the ability to compose events together or filter events. It's quite nifty.
Create an Action instead of an event. Your class may look like:
public class MyClass
{
// sender arguments <----- Use this action instead of an event
public Action<object, EventArgs> OnSomeEventOccured;
public void SomeMethod()
{
if(OnSomeEventOccured!=null)
OnSomeEventOccured(this, null);
}
}
have your singleton object check it's list of who it notifies and only call once if duplicated. Alternatively if possible reject event attachment request.
In silverlight you need to say e.Handled = true; in the event code.
void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true; //this fixes the double event fire problem.
string name = (e.OriginalSource as Image).Tag.ToString();
DoSomething(name);
}
Please tick me if this helps.

Categories