Reputation: 3135
I am trying to watch a value in c#, and trigger a function when it changes. Based on reading examples, I have:
//event watcher
private int _currentFrame =1;
public event System.EventHandler FrameChanged;
protected virtual void OnFrameChanged()
{
if (FrameChanged != null) FrameChanged(this, EventArgs.Empty);
}
public int Age
{
get
{
return _currentFrame;
}
set
{
//#3
_currentFrame = value;
OnFrameChanged();
}
}
and in my main function:
_currentFrame += _currentFrame;
As I understand it, this should trigger the event watcher, but it does not. What have i missed?
Thanks.
Upvotes: 1
Views: 253
Reputation: 391596
There are two things you need to do in order to get an event handler to be called.
You have neglected to show the first item in your code. If you haven't hooked up an event handler to your event you need to do that. You could do it like this:
someObject.FrameChanged += SomeObjectFrameChanged;
...
private void SomeObjectFrameChanged(object sender, EventArgs e)
{
... code here
}
The second looks OK on the surface, the property calls OnFrameChanged.
By the way, your OnFrameChanged is not the recommended way to implement event handler fire methods, you should use this template:
protected virtual void OnFrameChanged()
{
var evt = FrameChanged;
if (evt != null) evt(this, EventArgs.Empty);
}
The reason for this change, lifting the event value into a local variable is that if you're in a multithreaded environment, after you've checked that the event has at least one event handler (!= null
), another thread could unsubscribe the last event handler. Nitpicking but you should still change it.
In C# 6 you can change the above method to this:
protected virtual void OnFrameChanged()
{
FrameChanged?.Invoke(this, EventArgs.Empty);
}
As this will do all the same things.
But here we come to the real bug in your code and expectations:
_currentFrame += _currentFrame;
You expect this to fire your event, but this is incorrect.
You're accessing the backing field directly, which bypasses all the code in the property, thus there is no code here that calls OnFrameChanged
and thus the event will not be fired.
Instead you should access the property:
Age += Age;
Minor nitpicking #2 is that you should ensure that PropertyChanged
is only fired if the property actually changed:
Age = 1;
Age = 1; // did not change, do not fire PropertyChanged
And thus you should implement your property setter like this:
set
{
if (_currentFrame == value) return;
//#3
_currentFrame = value;
OnFrameChanged();
}
Upvotes: 1
Reputation: 4410
You haven't assigned no event to FrameChanged.
yourInstance.FrameChanged+= () => DoSomething();
Upvotes: 1