123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- using System;
- using System.ComponentModel;
- using System.Reflection;
- namespace HandyControl.Interactivity.Commands
- {
- /// <summary>
- /// Represents each node of nested properties expression and takes care of
- /// subscribing/unsubscribing INotifyPropertyChanged.PropertyChanged listeners on it.
- /// </summary>
- internal class PropertyObserverNode
- {
- private readonly Action _action;
- private INotifyPropertyChanged? _inpcObject;
- public PropertyInfo PropertyInfo { get; }
- public PropertyObserverNode? Next { get; set; }
- public PropertyObserverNode(PropertyInfo propertyInfo, Action action)
- {
- PropertyInfo = propertyInfo ?? throw new ArgumentNullException(nameof(propertyInfo));
- _action = () =>
- {
- action?.Invoke();
- if (Next == null) return;
- Next.UnsubscribeListener();
- GenerateNextNode();
- };
- }
- public void SubscribeListenerFor(INotifyPropertyChanged inpcObject)
- {
- _inpcObject = inpcObject;
- _inpcObject.PropertyChanged += OnPropertyChanged;
- if (Next != null) GenerateNextNode();
- }
- private void GenerateNextNode()
- {
- var nextProperty = PropertyInfo.GetValue(_inpcObject);
- if (nextProperty == null) return;
- if (nextProperty is not INotifyPropertyChanged nextInpcObject)
- throw new InvalidOperationException("Trying to subscribe PropertyChanged listener in object that " +
- $"owns '{Next?.PropertyInfo.Name}' property, but the object does not implements INotifyPropertyChanged.");
- Next?.SubscribeListenerFor(nextInpcObject);
- }
- private void UnsubscribeListener()
- {
- if (_inpcObject != null)
- _inpcObject.PropertyChanged -= OnPropertyChanged;
- Next?.UnsubscribeListener();
- }
- private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
- {
- if (e?.PropertyName == PropertyInfo.Name || string.IsNullOrEmpty(e?.PropertyName))
- {
- _action?.Invoke();
- }
- }
- }
- }
|