I'm tying myself in knots over a simple problem. I have a class that implements INotifyPropertyChanged
. Some of the instance properties' getters use static properties and thus their values may change if the static property changes? Here's a simplified example.
class ExampleClass : INotifyPropertyChanged { private static int _MinimumLength = 5; public static int MinimumLength { get { return _MinimumLength; } set { if (_MinimumLength != value) { _MinimumLength = value; //WHAT GOES HERE } } } private int _length = -1; public int length { get { return (_length > _MinimumLength) ? _length : _MinimumLength; } set { var oldValue = (_length > _MinimumLength) ? _length : _MinimumLength; if (_length != value) { _length = value; var newValue = (_length > _MinimumLength) ? _length : _MinimumLength; if (newValue != oldValue) { OnPropertyChanged("length"); } } } } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
Clearly if the static property MinimumLength
changes then every instance's property length
may also change. But how should the static property signal the possible change to the instances? It cannot call OnPropertyChanged
since that is not static.
I could keep a list at the class level of all the instances and call a method on each one, but somehow that feels like overkill. Or I could pull the static properties out into a singleton class but logically they live at the class level. Is there an established pattern for this or should I be thinking about this differently?
The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed. For example, consider a Person object with a property called FirstName .
To implement INotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated.
INotifyPropertyChanged works on instance properties. One solution is to use a singleton pattern and keep INotifyPropertyChanged, the other is to use your own event to notify listeners. EDIT: In WPF 4.5, they introduced property changed mechanic for static properties: You can use static properties as the source of a data binding.
But this time, INotifyPropertyChanged does not work. Any solution? INotifyPropertyChanged works on instance properties. One solution is to use a singleton pattern and keep INotifyPropertyChanged, the other is to use your own event to notify listeners.
Clearly if the static property MinimumLength changes then every instance's property length may also change. But how should the static property signal the possible change to the instances? It cannot call OnPropertyChanged since that is not static.
Using INotifyPropertyChanged is sometimes more flexible than using DependencyProperty. Let me explain that. When you build a screen on which a lot of controls visibility dependsof some rules, you may declare a boolean which value is computed from other boolean.
If you're inclined to maintain that design then I would go with a solution like the following:
public static int MinimumLength { get { return _MinimumLength; } set { if (_MinimumLength != value) { _MinimumLength = value; OnGlobalPropertyChanged("MinimumLength"); } } } static event PropertyChangedEventHandler GlobalPropertyChanged = delegate { }; static void OnGlobalPropertyChanged(string propertyName) { GlobalPropertyChanged( typeof (ExampleClass), new PropertyChangedEventArgs(propertyName)); } public ExampleClass() { // This should use a weak event handler instead of normal handler GlobalPropertyChanged += this.HandleGlobalPropertyChanged; } void HandleGlobalPropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "MinimumLength": if (length > MinimumLength) length = MinimumLength; break; } }
This is pretty much equivalent to maintaining a list of instances but I find it more maintainable and clearer. Also, you really need to use a weak event handler strategy, otherwise, your instances will not be garbage collected because they will always be associated with the static event which acts like a GC root.
You can read more about weak event handlers in the following blog posts (which were written by me so I'm biased):
.NET Weak Event Handlers – Part I
.NET Weak Event Handlers – Part I
In an unrelated note your code is currently firing property changed when in fact the property value did not change. For example:
You could use the technique mentioned in Binding static property and implementing INotifyPropertyChanged but also raise a notification against "length", e.g.
class ExampleClass : INotifyPropertyChanged { private static int _MinimumLength = 5; public int MinimumLength { get { return _MinimumLength; } set { if (_MinimumLength != value) { _MinimumLength = value; OnPropertyChanged("MinimumLength"); OnPropertyChanged("length"); } } } ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With