fire event from bool setter - c#

I'm trying to fire an event when a bool has actually changed value. I read that using a custom set and get method is one of the ways to do this. But I keep getting NullReferenceException: Object reference not set to an instance of an object
Public class Ball : MonoBehaviour {
public delegate void ballEvents();
public static event ballEvents OnBallStop;
private bool _previousValue = true;
private bool _ballStopped = true;
public bool BallHasStopped {
get {return _ballStopped;}
set {
_ballStopped = value;
if (_ballStopped != _previousValue){
_previousValue = _ballStopped;
if(value == true) {
print("stop");
OnBallStop(); // this causes the error
} else {
print("moving");
}
}
}
}

When an event has no handlers it is null, and so cannot be invoked. You can check for null and not invoke it unless there are handlers.

Related

Issue with property setter with an object and toolbox

This code works fine, I can check if a timecode is valid when the
property changes its value. But the problem is that I cannot set the
value of this property in the toolbox, because of the new ValidTimeCodeEventArgs.
Is there a way to fix this so I could
change the value in the toolbox and check if it is correct?
[Browsable(true)]
public event EventHandler<ValidTimeCodeEventArgs> ValidTimeCode;
private string strTimeCode;
[Category("Custom")]
[Browsable(true)]
[DefaultValue(typeof(string), "00:00:00:00")]
public string StrTimeCode {
get {
return strTimeCode;
}
set {
if (value != null) {
ValidTimeCode(this, new ValidTimeCodeEventArgs(IsValidTimeCode(value, FrameRate, IsDropFrame)));
strTimeCode = value;
initValue = strTimeCode;
Invalidate();
}
}
}
public class ValidTimeCodeEventArgs : EventArgs {
public ValidTimeCodeEventArgs(bool isValid) {
IsValid = isValid;
}
public bool IsValid { get; }
}
Your ValidTimeCode event probably doesn't have any subscribers when you try to raise it. Try:
ValidTimeCode?.Invoke(this, new ValidTimeCodeEventArgs(IsValidTimeCode(value, FrameRate, IsDropFrame)));
This basically does a null check on the handler (it's null if no one subscribed to the event), then only raises it if it isn't null. See here for more info.

Change data in Class when List<sub-class> data is changed

I have a class STimer that has a List in it. The serviceDetail is monitored on a timer very often, and rarely changes, but when it does change I want to get the fact that the data changed without looping through the list due to processing power. Maybe this is a duplicate question that I just don't know how to search for it, but I have been trying. Here is a code Sample:
class STimers
{
public class ServiceDetail
{
private int _serviceKey;
private bool _isRunning = true;
private bool _runningStateChanged = false;
public bool isRunning
{
get { return _isRunning; }
set
{
//Check to see if the data is the same, if so, don't change, if not, change and flag as changed
if(_isRunning = value) { return; }
else
{
_isRunning = value;
_runningStateChanged = true;
<-- Update STimers._dataChanged to true -->
}
}
}
}
public List<ServiceDetail> _serviceMonitors = new List<ServiceDetail>();
public bool _dataChanged = false;
}
I could do a .Find on the list to return all of the _serviceMonitors._runningStateChanged=true, but that seems like a lot of work parsing the List every time the timer fires, when likely only 1 out of 1,000 loops will actually have a change.
Is this even possible, or do I need to move the check for changes out of the class?
You could get this by adding an event to your ServiceDetail class
public class ServiceDetail
{
public event EventHandler<ListChangedEventArgs> ListChanged;
private int _serviceKey;
private bool _isRunning = true;
private bool _runningStateChanged = false;
private void OnListChanged(ListChangedEventArgs e){
if (ListChanged != null) ListChanged(this, e);
}
public bool isRunning
{
get { return _isRunning; }
set
{
//Check to see if the data is the same, if so, don't change, if not, change and flag as changed
if(_isRunning = value) { return; }
else
{
_isRunning = value;
_runningStateChanged = true;
OnListChanged(new ListChangedEventArgs(this));
<-- Update STimers._dataChanged to true -->
}
}
}
}
And define your ListChangedEventArgs class like this
public class ListChangedEventArgs:EventArgs
{
public ServiceDetail serviceDetail { get; set; }
public ListChangedEventArgs(ServiceDetail s)
{
serviceDetail = s;
}
}
And then register to the event for each servicedetail added to the list
s.ListChanged += (sender, args) => YourFunction();
Hope it helps

Event when boolean is true

I'm programming in c#(WPF). I have some Boolean variables in my class like isConnected or isBusy. I want to define a event and event handler for them to when my boolean variables are changed, I run a method.
I searched and find some things but I can't understand them.
could you help me to write it?
Update 1:
finally I write it, but I get StackOverFlowExeception which may be caused by recursion.
what is wrong?
public event EventHandler IsConnectedChanged;
public bool IsConnected
{
get { return IsConnected; }
set
{
IsConnected = value;
CheckAndCallHandlers();
}
}
private void CheckAndCallHandlers()
{
EventHandler handler = IsConnectedChanged;
if (IsConnected)
handler(this, EventArgs.Empty);
}
Wrap the variable in Properties, and then in the setter for the properties you can call a method that checks to see if both are true. When that condition is met, you can then do the extra work:
public class SomeClass
{
private bool _isConnected;
private bool _isBusy;
public event EventHandler SomeCustomEvent;
public bool IsConnected
{
get { return _isConnected; }
set
{
_isConnected = value;
CheckAndCallHandlers();
}
}
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
CheckAndCallHandlers();
}
}
private void CheckAndCallHandlers()
{
var handler = SomeCustomEvent;
if(IsConnected && IsBusy && handler != null)
handler(this, EventArgs.Empty);
}
}
make it a property
bool _isConnected;
bool isConnected
{
get { return _isConnected; }
set {
if (value != _isConnected) //it's changing!
{
doSomething();
}
_isConnected = value; //Could do this inside the if but I prefer it outside because some types care about assignment even with the same value.
}
}

Polling an object's public variable

I would like to notify a program immediately when there is a change in a bool variable that is a public variable of an object. For example;
say, an instance of class conn is created within a windows form application.
there is a Ready variable, a public variable of the class conn is present.
I would like to get notified whenever there is a change in this variable.
I did a quick research to solve this problem within stackoverflow but the answers suggested the use of property, which, I think is not suitable for my application.
I will assume you are referring to a field when you say public variable.
With few exceptions, it is preferable to not have public fields in C# classes, but rather private fields with public accessors:
class BadClass
{
public int Value; // <- NOT preferred
}
class GoodClass
{
private int value;
public int Value
{
get { return this.value; }
set { this.value = value; }
}
}
One of the reasons to structure your code this way is so you can do more than one thing in the property's getter and setters. An example that applies to your scenario is property change notification:
class GoodClass : INotifyPropertyChanged
{
private int value;
public int Value
{
get { return this.value; }
set
{
this.value = value;
this.OnPropertyChanged("Value");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(name);
}
}
}
If you were to implement your class like this, you could use it this way:
void SomeMethod()
{
var instance = new GoodClass();
instance.PropertyChanged += this.OnPropertyChanged;
}
void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Value")
{
// Do something here.
}
}
If you change the Value property, not only will it change the value of the underlying field, but it will also raise the PropertyChanged event, and call your event handler.
You want to use the Observer pattern for this. The most straight forward way to do this in .NET is the event system. In the class conn, create an event:
public event EventHandler ReadyChanged;
and then when you create an instance of conn, subscribe to that event:
o.ReadyChanged += (s, e) =>
{
// do something
}
and then finally, when the flag changes in conn, fire the event via a new method named OnReadyChanged:
protected virtual void OnReadyChanged()
{
if (ReadyChanged != null) { ReadyChanged(this, new EventArgs()); }
}

How to create an event on property changing and changed event in C#

I created a property
public int PK_ButtonNo
{
get { return PK_ButtonNo; }
set { PK_ButtonNo = value; }
}
Now I want to add events to this property for value changing and changed.
I wrote two events. Here I want both the events to contain changing value as well as changed value.
i.e
When user implements the event. He must have e.OldValue, e.NewValue
public event EventHandler ButtonNumberChanging;
public event EventHandler ButtonNumberChanged;
public int PK_ButtonNo
{
get { return PK_ButtonNo; }
private set
{
if (PK_ButtonNo == value)
return;
if (ButtonNumberChanging != null)
this.ButtonNumberChanging(this,null);
PK_ButtonNo = value;
if (ButtonNumberChanged != null)
this.ButtonNumberChanged(this,null);
}
}
How will I get the changing value and changed value when I implement this event.
Add the following class to your project:
public class ValueChangingEventArgs : EventArgs
{
public int OldValue{get;private set;}
public int NewValue{get;private set;}
public bool Cancel{get;set;}
public ValueChangingEventArgs(int OldValue, int NewValue)
{
this.OldValue = OldValue;
this.NewValue = NewValue;
this.Cancel = false;
}
}
Now, in your class add the changing event declaration:
public EventHandler<ValueChangingEventArgs> ButtonNumberChanging;
Add the following member (to prevent stackoverflow exception):
private int m_pkButtonNo;
and the property:
public int PK_ButtonNo
{
get{ return this.m_pkButtonNo; }
private set
{
if (ButtonNumberChanging != null)
ValueChangingEventArgs vcea = new ValueChangingEventArgs(PK_ButtonNo, value);
this.ButtonNumberChanging(this, vcea);
if (!vcea.Cancel)
{
this.m_pkButtonNo = value;
if (ButtonNumberChanged != null)
this.ButtonNumberChanged(this,EventArgs.Empty);
}
}
}
The "Cancel" property will allow the user to cancel the changing operation, this is a standard in a x-ing events, such as "FormClosing", "Validating", etc...

Categories

Resources