How to implement an event class - c#

This question is in reference to another question, mine is similar but I am asking for help beyond what I have read in this answer:
Raise an event whenever a property's value changed?
EDIT: What I am trying to accomplish is a global message "service" within the application such that I can write to the message variable from different places within the application and have the User Interface (winform) pick up on the fact that there was some change to that variable and based upon the event, I can read the message variable and display its content to the user. I hope this makes more sense now.
First, I am new to the world of C# and while I understand the code written as the most accepted answer, where I fail, is to understand the final implementation. If I place this code in a .cs file and I use the namespace in winform file how do I finalize the implementation? In my case, I would want to implement the class in the winform file so I can watch for an event to occur. Once the event occurred I would write some information to the user via the winform interface. I think I would need to use the "get" of the string...but not sure how the implementation would go? I apologize in advance if this doesn't make sense, I am trying to piece this all together. Thanks for any help on this!
For reference, I have start with the answer provide and altered it for my purposes:
public class Messaging : INotifyPropertyChanged
{
private string dLMessage;
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, e);
}
protected void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public string DLMessage
{
get { return dLMessage; }
set
{
if (value != dLMessage)
{
dLMessage = value;
OnPropertyChanged("DLMessage");
OnDLMessageChanged(EventArgs.Empty);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnDLMessageChanged(EventArgs e)
{
EventHandler handler = DLMessageChanged;
if (handler != null)
handler(this, e);
}
public event EventHandler DLMessageChanged;
}

Edit
According to your edited question, there are many different ways. One of those is making DLMesaage property and its change event static:
public class Messaging
{
private static string dLMessage;
public static string DLMessage
{
get { return dLMessage; }
set
{
if (value != dLMessage)
{
dLMessage = value;
OnDLMessageChanged(EventArgs.Empty);
}
}
}
protected static void OnDLMessageChanged(EventArgs e)
{
EventHandler handler = DLMessageChanged;
if (handler != null)
handler(null, e);
}
public static event EventHandler DLMessageChanged;
}
and then subscribe for event this way in all your different forms (for example in form load event)
Messaging.DLMessageChanged += msg_DLMessageChanged;
having this function in that form:
void msg_DLMessageChanged(object sender, EventArgs e)
{
MessageBox.Show("at last changed!");
}
You can unsubscribe for event this way:
Messaging.DLMessageChanged -= msg_DLMessageChanged;
For example if you subscribed for event in some forms, you can put unsubscribe code in Dispose override:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
Messaging.DLMessageChanged -= msg_DLMessageChanged;
components.Dispose();
}
base.Dispose(disposing);
}
This way if you close the form, the event never be handled in that form.
Please note that I am keeping things simple in order to get your job done with minimum changes.
Original
Put this some where you instantiate Messageing instance for example in your form's constructor or load event handler:
Messaging msg = new Messaging();
msg.DLMessageChanged += msg_DLMessageChanged;
Add this to the form:
void msg_DLMessageChanged(object sender, EventArgs e)
{
MessageBox.Show("at last changed!");
//You can access the new value using Messaging.DLMessage
}
And also it seems you don't need to implement INotifyPropertyChanged if you only want DLMessageChanged. Now you are raising both events.
Or in case you want to use PropertyChanged event, put this some where you instantiate Messageing instance for example in your form's constructor or load event handler:
Messaging msg = new Messaging();
msg.PropertyChanged+= msg_PropertyChanged;
Add this to the form:
void msg_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "DLMessage")
MessageBox.Show("at last changed!");
}

Related

The event can only appear in the left hand side of += or -+ [duplicate]

I have a base class that contains the following events:
public event EventHandler Loading;
public event EventHandler Finished;
In a class that inherits from this base class I try to raise the event:
this.Loading(this, new EventHandler()); // All we care about is which object is loading.
I receive the following error:
The event 'BaseClass.Loading' can only appear on the left hand side of += or -= (BaseClass')
I am assuming I cannot access these events the same as other inherited members?
What you have to do , is this:
In your base class (where you have declared the events), create protected methods which can be used to raise the events:
public class MyClass
{
public event EventHandler Loading;
public event EventHandler Finished;
protected virtual void OnLoading(EventArgs e)
{
EventHandler handler = Loading;
if( handler != null )
{
handler(this, e);
}
}
protected virtual void OnFinished(EventArgs e)
{
EventHandler handler = Finished;
if( handler != null )
{
handler(this, e);
}
}
}
(Note that you should probably change those methods, in order to check whether you have to Invoke the eventhandler or not).
Then, in classes that inherit from this base class, you can just call the OnFinished or OnLoading methods to raise the events:
public AnotherClass : MyClass
{
public void DoSomeStuff()
{
...
OnLoading(EventArgs.Empty);
...
OnFinished(EventArgs.Empty);
}
}
You can only access an event in the declaring class, as .NET creates private instance variables behind the scenes that actually hold the delegate. Doing this..
public event EventHandler MyPropertyChanged;
is actually doing this;
private EventHandler myPropertyChangedDelegate;
public event EventHandler MyPropertyChanged
{
add { myPropertyChangedDelegate += value; }
remove { myPropertyChangedDelegate -= value; }
}
and doing this...
MyPropertyChanged(this, EventArgs.Empty);
is actually this...
myPropertyChangedDelegate(this, EventArgs.Empty);
So you can (obviously) only access the private delegate instance variable from within the declaring class.
The convention is to provide something like this in the declaring class..
protected virtual void OnMyPropertyChanged(EventArgs e)
{
EventHandler invoker = MyPropertyChanged;
if(invoker != null) invoker(this, e);
}
You can then call OnMyPropertyChanged(EventArgs.Empty) from anywhere in that class or below the inheritance heirarchy to invoke the event.
I am assuming I cannot access these events the same as other inherited members?
Precisely. It's customary to provide a protected function OnXyz or RaiseXyz for each event in the base class to enable raising from inherited classes. For example:
public event EventHandler Loading;
protected virtual void OnLoading() {
EventHandler handler = Loading;
if (handler != null)
handler(this, EventArgs.Empty);
}
Called in the inherited class:
OnLoading();
You can try this way, It works for me:
public delegate void MyEventHaldler(object sender, EventArgs e);
public class B
{
public virtual event MyEventHaldler MyEvent;
protected override void OnChanged(EventArgs e)
{
if (MyEvent != null)
MyEvent(this, e);
}
}
public class D : B
{
public override event MyEventHaldler MyEvent;
protected override void OnChanged(EventArgs e)
{
if (MyEvent != null)
MyEvent(this, e);
}
}
not to resurrect an old thread but in case anybody is looking, what I did was
protected EventHandler myPropertyChangedDelegate;
public event EventHandler MyPropertyChanged
{
add { myPropertyChangedDelegate += value; }
remove { myPropertyChangedDelegate -= value; }
}
This lets you inherit the event in a derived class so you can invoke it without requiring to wrap the method while keeping the += syntax. I guess you could still do that with the wrapping methods if you did
public event EventHandler MyPropertyChanged
{
add { AddDelegate(value); }
remove { RemoveDelegate(value); }
}

C# Events - Raising, Subscribing from two different projects in one solution

My goal is to create an event, raise the event in Project #1, have Project #2 subscribe to the event so that I can hit some code in Project #2. I was advised to do it this way because I cannot reference the code in Project #2.
I'm not familiar with events and have been researching the last hour. Is there anyone that can provide example code on how to do this? What I have now is not working.
// Creating the event
public event EventHandler UpdateUIEvent;
// Raising the event in Project #1
protected override void ResetProperties()
{
this.filePath = string.Empty;
EventArgs e = new EventArgs();
UpdateUIEvent(this, e); // this kills my program
}
// Subscribing to the event in Project #2
protected override void ClearAll()
{
boEncrypt.UpdateUIEvent += new EventHandler ?? // Not sure how to subscribe here
tbFile.text = string.Empty;
}
You're close... Please read the docs as usual for a better understanding of what needs to be where.
For your code, here's what we'll do:
In project 1, incorporate Michael HB's good recommendation to always check if there's any subscribers.
public class ProjectOneClass
{
public event EventHandler UpdateUIEvent;
// other stuff
protected override void ResetProperties()
{
this.filePath = string.Empty;
EventArgs e = new EventArgs();
var handler = UpdateUIEvent;
if (handler != null)
UpdateUIEvent(this, e);
}
}
Then in project 2, you have to have a reference to the event, which means you also need a reference to the class that contains it. You define a method in the class in project 2 that has the same signature as the event in project 1. In your case (in many cases) this signature is void (object sender, EventArgs e). EventHandler is a pre-defined delegate with this signature.
"Subscribing" to the event is adding your new method to the handler, like pOne.UpdateUIEvent += SomeMethodWithTheSameSignature; You're basically saying "whenever UpdateUIEvent is called, call this other method as well".
So now that we know that we can have a method called when the event fires, we need to define that event. If you want to call ClearAll() when the event fires, that's what goes in the method body.
public class ProjectTwoClass
{
public ProjectOneClass pOne;
// other stuff
public ProjectTwoClass()
{
pOne = new ProjectOneClass();
pOne.UpdateUIEvent += POneOnUpdateUIEvent;
}
public void POneOnUpdateUIEvent(object sender, EventArgs eventArgs)
{
ClearAll();
}
private void ClearAll()
{
tbFile.Text = string.Empty; // could probably just call tbFile.Clear();
}
}
Before raising an event, you should always check if it is not null.
protected override void ResetProperties()
{
this.filePath = string.Empty;
EventArgs e = new EventArgs();
var handler = UpdateUIEvent;
if(handler != null)
UpdateUIEvent(this, e);
}
Even when you are in different projects, you should only matter about the "public" keyword (internal or private won't work).
In project #2, you'll have
protected overeride void ClearAll()
{
boEncrypt.UpdateUIEvent += yourFunctionToTriggerWhenTheEventIsRaised;
tbFile.text = string.Empty;
}

NumericUpDown differentiate up and down

I have a WinForm with some numreicUpDown Controls, i want to know if the value has been incremented or decremented. the control fires the event value changed for both situations, and as far as i can understand the programm calls the methods UpButton and DownButton. Is there any other way to know how the value has been changed or do i have to do this with this methods(like firing eventor implementig my code in Up-Down-Button)
There is no standart way to do this.
I sugest to remember the old value and compare it with new one
decimal oldValue;
private void ValueChanged(object sender, EventArgs e)
{
if (numericUpDown.Value > oldValue)
{
}
else
{
}
oldValue = numericUpDown.Value;
}
Create your own control that overrides those UpButton and DownButton methods:
using System.Windows.Forms;
public class EnhancedNUD : NumericUpDown
{
public event EventHandler BeforeUpButtoning;
public event EventHandler BeforeDownButtoning;
public event EventHandler AfterUpButtoning;
public event EventHandler AfterDownButtoning;
public override void UpButton()
{
if (BeforeUpButtoning != null) BeforeUpButtoning.Invoke(this, new EventArgs());
//Do what you want here...
//Or comment out the line below and do your own thing
base.UpButton();
if (AfterUpButtoning != null) AfterUpButtoning.Invoke(this, new EventArgs());
}
public override void DownButton()
{
if (BeforeDownButtoning != null) BeforeDownButtoning.Invoke(this, new EventArgs());
//Do what you want here...
//Or comment out the line below and do your own thing
base.DownButton();
if (AfterDownButtoning != null) AfterDownButtoning.Invoke(this, new EventArgs());
}
}
Then when you implement the control on your form, you can hook up some of the events to let you know which button was clicked or key (up/down) hit.

Handling OnPropertyChanged

I'm not well versed in event-based programming. Basically, I'm still stumbling around with it. I'm trying to get something set up, but even with the tutorials, I can't wrap my head around it. What I would like to do (in words) is the following:
I have a dataobject where a property changes. I notice this in the setter of the property, and want to raise an event that the property has changed.
Elsewhere (in a different class entirely), I want to know that the property on this object has changed, and take some action.
Now I'm sure this is a common enough scenario, but my google-fu is letting me down. I'm simply not understanding http://msdn.microsoft.com/en-us/library/ms743695.aspx.
I have this:
public class ChattyClass {
private int someMember;
public event PropertyChangedEventHandler PropertyChanged;
public int SomeMember {
get {
return this.someMember;
}
set {
if (this.someMember != value){
someMember = value;
// Raise event/fire handlers. But how?
}
}
}
public class NosyClass{
private List<ChattyClass> myChatters;
public void addChatter(ChattyClass chatter){
myChatters.add(chatter);
// Start listening to property changed events
}
private void listner(){
// I want this to be called when the PropertyChangedEvent is called
Console.WriteLine("Hey! Hey! Listen! A property of a chatter in my list has changed!");
}
}
What do I do to wire this up?
Concerning the comment pointing me back to the link:
In the example I see:
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
What I'm not understanding:
Why isn't this just calling PropertyChanged(this, new PropertyCHangedEventArgs(name))
Where does PropertyChanged get assigned?
What does the assignment look like?
You have to fire the event. In the example on MSDN, they made a protected method OnPropertyChanged to handle this easier (and to avoid duplicate code).
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
What this method does, is look whether there is an event handler assigned or not (if it is not assigned and you just call it, you'll get a NullReferenceException). If there is one assigned, call this event handler. The event handler provided, has to have the signature of the PropertyChangedEventHandler delegate. This signature is:
void MyMethod(object sender, PropertyChangedEventArgs e)
Where the first parameter has to be of the type object and represents the object that fires the event, and the second parameter contains the arguments of this event. In this case, your own class fires the event and thus give this as parameter sender. The second parameter contains the name of the property that has changed.
Now to be able to react upon the firing of the event, you have to assign an event handler to the class. In this case, you'll have to assign this in your addChatter method. Apart from that, you'll have to first define your handler. In your NosyClass you'll have to add a method to do this, for example:
private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("A property has changed: " + e.PropertyName);
}
As you can see, this method corresponds to the signature I explained before. In the second parameter, you'll be able to find the information of which parameter has been changed. Last thing to do, is add the event handler. Now in your addChatter method, you'll have to assign this:
public void AddChatter(ChattyClass chatter)
{
myChatters.Add(chatter);
// Assign the event handler
chatter.PropertyChanged += new PropertyChangedEventHandler(chatter_PropertyChanged);
}
I would suggest you to read something about events in .NET / C#: http://msdn.microsoft.com/en-us/library/awbftdfh . I think after reading/learning this, things will be more clear to you.
You can find a console application here on pastebin if you would like to test it quickly (just copy/paste into a new console application).
With newer versions of C#, you can inline the call to the event handler:
// inside your setter
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProperty)));
You could also use something like Fody PropertyChanged to automatically generated the necessary code (visit the link to their GitHub page, with samples).
The link that you looked is for the MVVM pattern and WPF. It is not a general C# implementation. You need something like this:
public event EventHandler PropertyChanged;
public int SomeMember {
get {
return this.someMember;
}
set {
if (this.someMember != value) {
someMember = value;
if (PropertyChanged != null) { // If someone subscribed to the event
PropertyChanged(this, EventArgs.Empty); // Raise the event
}
}
}
...
public void addChatter(ChattyClass chatter) {
myChatters.add(chatter);
chatter.PropertyChanged += listner; // Subscribe to the event
}
// This will be called on property changed
private void listner(object sender, EventArgs e){
Console.WriteLine("Hey! Hey! Listen! A property of a chatter in my list has changed!");
}
If you want to know what property has changed you need to change your event definition to:
public event PropertyChangedEventHandler PropertyChanged;
And change the calling to:
public int SomeMember {
get {
return this.someMember;
}
set {
if (this.someMember != value){
someMember = value;
if (PropertyChanged != null) { // If someone subscribed to the event
PropertyChanged(this, new PropertyChangedEventArgs("SomeMember")); // Raise the event
}
}
}
private void listner(object sender, PropertyChangedEventArgs e) {
string propertyName = e.PropertyName;
Console.WriteLine(String.Format("Hey! Hey! Listen! a {0} of a chatter in my list has changed!", propertyName));
}
why isn't this just calling PropertyChanged(this, new
PropertyCHangedEventArgs(name))
Because if no one attached an handler to the event, then the PropertyChanged object returns null. So you'll have to ensure it's not null before calling it.
where does PropertyChanged get assigned?
In the "listener" classes.
For example, you could write in other class:
ChattyClass tmp = new ChattyClass();
tmp.PropertyChanged += (sender, e) =>
{
Console.WriteLine(string.Format("Property {0} has been updated", e.PropertyName));
};
What does the assignment look like?
In C# we use the assignment operators += and -= for events. I recommend reading the following article to understand how to write event handlers using the anonymous method form (example above) and the "old" form.
From taking the original code, and incorporating #Styxxy 's answer, I come out with:
public class ChattyClass : INotifyPropertyChanged
{
private int someMember, otherMember;
public int SomeMember
{
get
{
return this.someMember;
}
set
{
if (this.someMember != value)
{
someMember = value;
OnPropertyChanged("Some Member");
}
}
}
public int OtherMember
{
get
{
return this.otherMember;
}
set
{
if (this.otherMember != value)
{
otherMember = value;
OnPropertyChanged("Other Member");
}
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class NosyClass
{
private List<ChattyClass> myChatters = new List<ChattyClass>();
public void AddChatter(ChattyClass chatter)
{
myChatters.Add(chatter);
chatter.PropertyChanged+=chatter_PropertyChanged;
}
private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("A property has changed: " + e.PropertyName);
}
}

Question about custom events

I'm making custom events for C# and sometimes it isn't working.
This is how I'm making the event happen:
private bool isDoorOpen;
public bool IsDoorOpen {
get { return isDoorOpen;}
private set { isDoorOpen = value; DoorsChangeState(this, null);}
}
And these are the event declarations:
//events
public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
public event ChangedEventHandler PositionChanged;
public event ChangedEventHandler DirectionChanged;
public event ChangedEventHandler BreaksChangeState;
public event ChangedEventHandler DoorsChangeState;
This works as long as there are methods attached to the events, but if there isn't, it throws a null ref exception. What am I doing wrong?
The recommended way to call an event is
var handler = this.DoorsChangeState;
if (handler != null)
handler(this, null);
The reason for copying the handler locally is incase the event handler changes on another thread while you're checking for null.
EDIT: Found the article talking about race conditions.
http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx
I know this question has been discussed (and answered) several times here on SO.
Also somewhere here i got the following extension methods to make this pattern more easy to use:
public static class EventHandlerExtensions
{
public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
var temp = handler;
if (temp != null)
{
temp(sender, args);
}
}
public static void FireEvent(this EventHandler handler, object sender)
{
var temp = handler;
if (temp != null)
{
temp(sender, EventArgs.Empty);
}
}
}
So in your code you can say:
public bool IsDoorOpen
{
get { return isDoorOpen;}
private set
{
isDoorOpen = value;
DoorsChangeState.FireEvent(this);
}
}
If a event isn't subscribed to when it fires, a NullReferenceException will be thrown. This is correct behaviour, not something you've done wrong.
You should check:
if(DoorsChangeState != null)
{
DoorsChangeState(this, null); // Only fire if subscribed to
}
Before invoking an event you must check if the event is null:
if (DoorsChangeState != null)
DoorsChangeState(this, null);
When DoorsChangeState is null that means there are no listeners on that event.
You need to check to see if the event has been subscribed to.
I use this standard form for throwing all of my events.
var temp = EventName;
if(EventName!= null)
temp(this, null);

Categories

Resources