Reputation: 302
I would like to be notified with a PropertyChanged event raised from a class MyClass
implementing an interface IMyInterface
. The instance of this class is retrieved with DependencyService.Get<IMyInterface>();
Now, this is the class (Android project), in which there is a property with a backing field:
class MyClass : IMyInterface {
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
private set { _isEnabled = value; OnPropertyChanged("IsEnabled"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public void OnSomethingHappens() { //This method is called when something particular happens
/* Some code... */
IsEnabled = true; //The point where the property is changed
/* ...some other code */
}
}
The interface (Forms project) looks like this:
public interface IMyInterface : INotifyPropertyChanged
{
/* code relating the interface */
}
This interface is implementing INotifyPropertyChanged
in order to have the possibility to listen to a property change (as seen in the class above). So far, so good.
The problem is when, in my Forms project, I register an event handler with this:
_myService = DependencyService.Get<IMyInterface>();
_myService.PropertyChanged += (sender, e) => { /* do stuff */ };
But when the property in my implementing class changes, PropertyChanged
results null, and this means that the event is never fired.
I would like to add a little thing: recently, I experienced that accessing a non-static list property with DependencyService.Get<IMyInterface>().MyList
was useless, since MyList
resulted to be of size 0
, even if this list was filled inside the implementing class. I solved this using a static property. Maybe this is related to the issue above.
I would like to understand what I am mistaking in order to have this PropertyChanged
event working correctly.
Upvotes: 1
Views: 1650
Reputation: 302
Ok, I figured out how to solve this.
Basically, I created a property with a private static event
backing field, as follows:
private static event PropertyChangedEventHandler _propertyChanged;
public PropertyChangedEventHandler PropertyChanged
{
get { return _propertyChanged; }
set { _propertyChanged = value; }
}
This way, I could have the following code working properly:
protected void OnPropertyChanged(string name)
{
_propertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
Infact, _propertyChanged
was not null
anymore, since I subscribed to the event with the following code (formally identical to the one posted on my question, with the difference that I used the PropertyChanged
property backed with the private static field _propertyChanged
):
_myService = DependencyService.Get<IMyInterface>();
_myService.PropertyChanged += (sender, e) => { /* do stuff */ };
Now I think that this was necessary because I am using DependencyService
, otherwise, in normal code, this issue should not come out.
Anyway, I am guessing if the idea of having a EventHandler
property backed with a private static event
field is a good code practice or just sounds weird. But it works, and it works pretty good.
But, in order to do all of this, I had to change this:
public interface IMyInterface : INotifyPropertyChanged
{
/* code relating the interface */
}
to this:
public interface IMyInterface
{
PropertyChangedEventHandler PropertyChanged { get; set; }
/* code relating the interface */
}
I had to add that property in IMyInterface
so that I could access it from my Forms project code.
Moreover, I no more implement INotifyPropertyChanged
, because INotifyPropertyChanged
asks me to implement the interface with a:
public event PropertyChangedEventHandler PropertyChanged
inside my implementing class, but I substituted it with
private static event PropertyChangedEventHandler _propertyChanged;
public PropertyChangedEventHandler PropertyChanged
{
get { return _propertyChanged; }
set { _propertyChanged = value; }
}
as I exposed above.
Upvotes: 1