error learning how to use custom events - c#

i'm learning how to use custom events in c#, but i get some errors
i get "An object reference is required for the nonstatic field, method, or property" in the bold words
so i tried following this
but case 1 couldn't be tried 'cause TypeChanged is already a nonstatic method (i think)
in case 2 i get "impossible to acces BicycleType as an instance reference, qualify it as a type"
public class Bicycle
{
public event EventHandler TypeChanged;
private string type;
...
public string BicycleType {
get { return this.type; }
set {
this.type = value;
if (this.TypeChanged != null)
this.TypeChanged( this, new EventArgs() );
}
}
public Bicycle() {}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("heila!");
Bicycle istanza = new Bicycle();
istanza.TypeChanged += new EventHandler(**istanza_TypeChanged**);
istanza.BicycleType = "io";
Console.WriteLine("io");
}
void istanza_TypeChanged(object sender, EventArgs e) {
Console.WriteLine("rofkd");
}
}
the tutorial i followed told me i can use events "as" methods, maybe i'm wrong here?
the code is completely similar to te tutorial code
sorry for my bad english and thanks in advance

As you are registering the event from the main method, which is static, the event handler (istanza_TypeChanged) has to be made static too.

You problem is that Main is static and can therefore not access nonstatic members of the class Program. However you try to access istanza_TypeChanged. That is what is causing your exception.
You have to make istanza_TypeChanged static too to solve the issue
class Program
{
static void Main(string[] args)
{
Console.WriteLine("heila!");
Bicycle istanza = new Bicycle();
istanza.TypeChanged += new EventHandler(**istanza_TypeChanged**);
istanza.BicycleType = "io";
Console.WriteLine("io");
}
static void istanza_TypeChanged(object sender, EventArgs e)
{
Console.WriteLine("rofkd");
}
}

Register the event from a non-static context or change your event to be static.

Change istanza_TypeChanged to the following:
private static void istanza_TypeChanged(object sender, EventArgs e)
{
Console.WriteLine("rofkd");
}
The following fired the event for me:
public class Bicycle
{
public event EventHandler TypeChanged;
private string type;
public string BicycleType
{
get { return this.type; }
set
{
this.type = value;
if (this.TypeChanged != null)
this.TypeChanged(this, new EventArgs());
}
}
public Bicycle()
{
}
private class Program
{
private static void Main(string[] args)
{
Console.WriteLine("heila!");
Bicycle istanza = new Bicycle();
istanza.TypeChanged += istanza_TypeChanged;
istanza.BicycleType = "io";
Console.WriteLine("io");
}
private static void istanza_TypeChanged(object sender, EventArgs e)
{
Console.WriteLine("rofkd");
}
}
}

Related

C# - Why is there an error using EventHandler<T>?

Doing a Pluralsight video and can't find out why it's wrong.
Error Message on this point:
worker.WorkPerformed += new EventHandler<WorkPerformedEventArgs>(worker_WorkPerformed);
Error Message:
Cannot implicity convert to type
'System.EventHandler<AB_Events.WorkPerformedEventArgs>' to
'AB_Events.WorkPerformedHandler'
Snippets
public delegate int WorkPerformedHandler(object sender,WorkPerformedEventArgs e);
public class Worker
{
public event WorkPerformedHandler WorkPerformed;
protected virtual void OnWorkPerformed(int hours, WorkType workType)
{
var del = WorkPerformed as WorkPerformedHandler;
if (del != null)
{
del(this, new WorkPerformedEventArgs(hours, workType));
}
}
}
And
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
worker.WorkPerformed += new EventHandler<WorkPerformedEventArgs>(worker_WorkPerformed);
Console.ReadKey();
}
public static void worker_WorkPerformed(object sender, WorkPerformedEventArgs e)
{
throw new NotImplementedException();
}
}
Although methods and anonymous functions are implicitly convertible to a delegate type that matches their signature, a delegate instance is not implicitly convertible to another delegate type.
You need to use either EventHandler<TEventArgs> or your WorkPerformedHandler, but not both:
public class Worker
{
public event WorkPerformedHandler WorkPerformed;
//...
}
Or:
public class Worker
{
public event EventHandler<WorkPerformedEventArgs> WorkPerformed;
//...
}
Also, because worker_WorkPerformed can be implicitly converted to either type, the most concise syntax would be this:
worker.WorkPerformed += worker_WorkPerformed; // Implicit conversion
If you do go with your WorkPerformedHandler delegate, make sure you change the return type to void as per the signature of worker_WorkPerformed:
public delegate void WorkPerformedHandler(object sender, WorkPerformedEventArgs e);
It is generally not advisable to return from an event handler anyway, as there can be multiple subscribers.
what i have done is to replace WorkPerformedHandler by EventHandler<WorkPerformedEventArgs>
public delegate int WorkPerformedHandler(object sender, WorkPerformedEventArgs e);
public class Worker
{
public event EventHandler<WorkPerformedEventArgs> WorkPerformed;
protected virtual void OnWorkPerformed(WorkPerformedEventArgs e)
{
WorkPerformed?.Invoke(this, e);
}
}
event subscription :
var worker = new Worker();
worker.WorkPerformed += new EventHandler<WorkPerformedEventArgs>(worker_WorkPerformed);

How implement a delegation pattern in c# using delegates?

I want to implement delegation pattern using delegates
public class Cat {
private delegate void SoundDelegate();
private SoundDelegate sound;
public Cat() {
sound = new SoundDelegate(SomeClass.DoSound1);
}
public void DoSound() {
sound();
}
}
public class PussyCat {
private delegate void SoundDelegate();
private SoundDelegate sound;
public PussyCat() {
sound = new SoundDelegate(SomeClass.DoSound2);
}
public void DoSound() {
sound();
}
}
public class SomeClass {
public static void DoSound1() {
Console.WriteLine("Sound 1");
}
public static void DoSound2() {
Console.WriteLine("Sound 2");
}
}
Does this code impelement the delegation pattern? I mean can I use delegates for implement delegation pattern or this way is incorrect.
And if the previous example is correct and I can use delegates to implement the delegation pattern and implement the observer pattern, then what is the difference between the observer pattern and the delegation pattern and what is similar?
The difference between delegation and observer patterns is a level of control your class has over the delegate/observer.
In case of delegate, it's assumed that your class has full control over how delegated class should be used. The observable class has no idea of how exactly it would be used by other classes.
It's also often assumed that observable class could have any number of observers while delegate is usually one.
I also simplified the code provided trying to avoid unnecessarily class PussyCat, so the original class could be configured to use any delegate in runtime.
You can also find CatObservable class to understand the idea of observable-observer implementation.
class Program
{
static void Main(string[] args)
{
Cat cat1 = new Cat(SomeClass.DoSound1);
Cat cat2 = new Cat(SomeClass.DoSound2);
CatObservable cat3 = new CatObservable();
cat3.Sound += Cat3_Sound;
cat3.Sound += (object sender, EventArgs e) => { SomeClass.DoSound1(); } ;
cat3.Sound += (object sender, EventArgs e) => { SomeClass.DoSound2(); };
}
private static void Cat3_Sound(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
public class Cat
{
public delegate void SoundDelegate();
public SoundDelegate Sound { get; set; }
public Cat(SoundDelegate soundDelagate)
{
Sound = soundDelagate;
}
protected void DoSound()
{
if (Sound!=null)
Sound();
}
}
public class CatObservable
{
public event EventHandler Sound;
public CatObservable()
{
}
protected void DoSound()
{
if (Sound != null)
Sound(this, EventArgs.Empty);
}
}
public class SomeClass
{
public static void DoSound1()
{
Console.WriteLine("Sound 1");
}
public static void DoSound2()
{
Console.WriteLine("Sound 2");
}
}

get publisher class field from sender

I want to get my field >>> NumberOfElementsInMyList from sender, How Can I do it? I couldn't find this kind of question here (what I have seen, was about windows forms), so ...
class Program
{
static void Main(string[] args)
{
Publisher PublisherObject = new Publisher();
PublisherObject.NumberAdded += PublisherObject_NumberAdded;
PublisherObject.AddNumber(int.Parse(Console.ReadLine());
}
static void PublisherObject_NumberAdded(object sender, EventArgs e)
{
//I want to write on the console "NumberOfElementsInMylist"
//I tried:
//sender.NumberOfElementsInMylist -- not works
//Publisher obj=(publisher)sender and then sender.NumberOfElementsInMylist
//not works
Console.WriteLine("number of elements in list is ---> "+ ???? );
}
}
class Publisher
{
public event EventHandler NumberAdded;
public int NumberOfElementsInMyList;
List<int> MyList=new List<int>();
public void AddNumber(int NumberToAdd)
{
MyList.Add(NumberToAdd);
NumberOfElementsInMyList = MyList.Count;
NumberAdded(this, new EventArgs());
}
}
To literally answer your question, the reason why you can't access the NumberOfElementsInMyList field is because when you create the EventArgs, your instance of Publisher is being cast as an object (which you can do since all classes inherit from object.) So to see the properties (or field) of Publisher, you have to cast the sender as Publisher.
var numberOfElements = ((Publisher)sender).NumberOfElementsInMyList;
A downside to this is that hypothetically, sender might not be a Publisher. Because sender is an object, it could technically be anything.
You can also create your own event handler delegate and event args instead of using the boilerplate EventHandler delegate.
public delegate void NumberAdded(Publisher source, NumberAddedEventArgs eventArgs);
public class NumberAddedEventArgs : EventArgs
{
public NumberAddedEventArgs(int numberAdded, numberOfItemsInList)
{
NumberAdded = numberAdded;
NumberOfItemsInList = numberOfItemsInList;
}
public int NumberAdded { get; private set; }
public int NumberOfItemsInList { get; private set; }
}
public class Publisher
{
public event EventHandler NumberAddedEvent;
public int NumberOfElementsInMyList;
List<int> MyList = new List<int>();
public void AddNumber(int NumberToAdd)
{
MyList.Add(NumberToAdd);
NumberOfElementsInMyList = MyList.Count;
NumberAddedEvent?.Invoke(this, new NumberAddedEventArgs(NumberToAdd,
NumberOfElementsInMyList));
}
}
var numberOfElementsInList = args.NumberOfItemsInList; // much better!
The (object sender, EventArgs args) is a strange convention. In any other scenario we would create strongly-typed methods and delegates. But in this case there's a tendency to use something that's not strongly-typed because it's a convention.
You can simply cast the sender, can't you?
var publisher = (Publisher)sender;
Console.WriteLine(publisher.NumberOfElementsInMyList);
Or more safely:
Console.WriteLine(
(sender as Publisher)?.NumberOfElementsInMyList?.ToString() ?? "sender is not a publisher!");

Visual C# returning value from an event handler

I have a form that has a button to get a method executed in another class.
Code on the form:
public delegate void CustomPreviewCreate();
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
CustomPreviewCreate_Do();
}
}
This event then gets handled in another class. What I would like to achieve is that I can feed back to the form some form of return value if the method correctly executed.
What I tried so far does not get me the result.
Here is the code:
public void Initialize()
{
SubAsstViewPartControl.CustomPreviewCreate_Do += SubAsstViewPartControl_CustomPreviewCreate_Do;
// this gives me a the compiler error that the return type is wrong
}
private bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return false;
}
Is there any direct way to return value from an event handler or I need to use a separate static field to store the event result in?
Update:
Per #Jon's comment, which seemed the simplest to me, I added an answer below demonstrating the simplest approach.
The common approach is to encapsulate your value in the type of EventArgs your event expects. For example, the Framework's CancelEventArgs contains a settable bool Cancel property, allowing each CancelEventHandler to assign a value. The sender can then read the property after the event has been invoked. You could also use a container-like EventArgs class if you want to collect separate values from individual event handlers. For example:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class SingleValueEventArgs : EventArgs
{
public int Value { get; set; }
}
public class MultiValueEventArgs : EventArgs
{
private List<int> _values = new List<int>(); // Private to prevent handlers from messing with each others' values
public IEnumerable<int> Values
{
get { return _values; }
}
public void AddValue(int value) { _values.Add(value); }
}
public class Exposer
{
public event EventHandler<SingleValueEventArgs> WantSingleValue;
public event EventHandler<MultiValueEventArgs> WantMultipleValues;
public void Run()
{
if (WantSingleValue != null)
{
var args = new SingleValueEventArgs();
WantSingleValue(this, args);
Console.WriteLine("Last handler produced " + args.Value.ToString());
}
if (WantMultipleValues != null)
{
var args = new MultiValueEventArgs();
WantMultipleValues(this, args);
foreach (var value in args.Values)
{
Console.WriteLine("A handler produced " + value.ToString());
}
}
}
}
public class Handler
{
private int _value;
public Handler(Exposer exposer, int value)
{
_value = value;
exposer.WantSingleValue += exposer_WantSingleValue;
exposer.WantMultipleValues += exposer_WantMultipleValues;
}
void exposer_WantSingleValue(object sender, SingleValueEventArgs e)
{
Console.WriteLine("Handler assigning " + _value.ToString());
e.Value = _value;
}
void exposer_WantMultipleValues(object sender, MultiValueEventArgs e)
{
Console.WriteLine("Handler adding " + _value.ToString());
e.AddValue(_value);
}
}
class Program
{
static void Main(string[] args)
{
var exposer = new Exposer();
for (var i = 0; i < 5; i++)
{
new Handler(exposer, i);
}
exposer.Run();
}
}
}
Per Jon Skeet's comment, which seemed the simplest to me, the simplest approach seems to be as follows:
public delegate bool CustomPreviewCreate(); // here we declare a return type
public static event CustomPreviewCreate CustomPreviewCreate_Do;
private void CreatePreview()
{
if (CustomPreviewCreate_Do !=null)
{
bool returnval = CustomPreviewCreate_Do();
}
}
And then:
// the method is declared to return the same type
bool SubAsstViewPartControl_CustomPreviewCreate_Do()
{
// do stuff
return true; // return the value of the type declared
}

Redirecting Events to handlers inside custom controls

I have mad a custom control. and i need to redirect the Event handler. i have cut the code down dramatically to try and articulate what im trying to do.
public class RemoteDesktop : WindowsFormsHost
{
public event OnConnectingEventHandler OnConnecting;
public delegate void OnConnectingEventHandler(object sender, EventArgs Arguments);
public event OnDisconnectingEventHandler OnDisconnecting;
public delegate void OnDisconnectingEventHandler(Object sender, IMsTscAxEvents_OnDisconnectedEvent Arguments);
private AxMsRdpClient7NotSafeForScripting RDPUserControl = new AxMsRdpClient7NotSafeForScripting();
public RemoteDesktop()
{
this.RDPUserControl.BeginInit();
this.RDPUserControl.SuspendLayout();
base.Child = RDPUserControl;
this.RDPUserControl.ResumeLayout();
this.RDPUserControl.EndInit();
}
}
public class RemoteDesktopViewModel
{
public RemoteDesktopViewModel()
{
RemoteDesktop newRDC = new RemoteDesktop();
newRDC.OnConnecting += new RemoteDesktop.OnConnectingEventHandler(newRDC_OnConnecting);
}
void newRDC_OnConnecting(object sender, EventArgs Arguments)
{
//DoStuff
}
}
basically it all works, i can connect and disconnect to the remote computer however i cannot get the fired events to occur in my view model.
Can anyone help me figure out how i can point my events correctly.
Thank you.
Thanks to some help i have the resolution
Step 1:
Declare delegates outside the class (within the namespace)
Step 2:
Declare the events to be called for the control.
Step 3: use the event handlers of the controls to reise the delegates you created
Completed Code
public delegate void OnConnectingEventHandler(object sender, EventArgs Arguments);
public delegate void OnDisconnectingEventHandler(Object sender,IMsTscAxEvents_OnDisconnectedEvent Arguments);
public class RemoteDesktop : WindowsFormsHost
{
public event OnConnectingEventHandler IsConnecting;
public event OnDisconnectingEventHandler IsDisconnecting;
private AxMsRdpClient7NotSafeForScripting RDPUserControl = new AxMsRdpClient7NotSafeForScripting();
public RemoteDesktop()
{
this.RDPUserControl.BeginInit();
this.RDPUserControl.SuspendLayout();
base.Child = RDPUserControl;
this.RDPUserControl.ResumeLayout();
this.RDPUserControl.EndInit();
RDPUserControl.OnConnecting += RemoteDesktop_OnConnecting;
RDPUserControl.OnDisconnected += RDPUserControl_OnDisconnected;
}
void RDPUserControl_OnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
{
IsDisconnecting(sender, e);
}
void RemoteDesktop_OnConnecting(object sender, EventArgs Arguments)
{
IsConnecting(sender, Arguments);
}
}
public class RemoteDesktopViewModel
{
public RemoteDesktopViewModel()
{
RemoteDesktop newRDC = new RemoteDesktop();
newRDC.IsConnecting += new RemoteDesktop.OnConnectingEventHandler(newRDC_OnConnecting);
}
void newRDC_OnConnecting(object sender, EventArgs Arguments)
{
//DoStuff
}
}
//at the constractor of the class
OnConnecting+=RDC_OnConnecting;
then you can write your logic in method:newRDC_OnConnecting. make sure OnConnectingEventHandler have same method signatures with newRDC_OnConnecting.

Categories