WPF INotifyPropertyChanged for linked read-only properties

后端 未结 7 1324
小鲜肉
小鲜肉 2020-12-30 09:22

I am trying to understand how to update the UI if I have a read-only property that is dependent on another property, so that changes to one property update both UI elements

相关标签:
7条回答
  • 2020-12-30 10:09

    I realize this is an old question, but it's the first Google result of "NotifyPropertyChanged of linked properties", so I think it's appropriate to add this answer so that there's some concrete code.

    I used Robert Rossney's suggestion and created a custom attribute, then used it in a base view model's PropertyChanged event.

    The attribute class:

    [AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
    public class DependsOnPropertyAttribute : Attribute
    {
        public readonly string Dependence;
    
        public DependsOnPropertyAttribute(string otherProperty)
        {
            Dependence = otherProperty;
        }
    }
    

    And in my base view model (which all other WPF view models inherit from):

    public abstract class BaseViewModel : INotifyPropertyChanged
    {
        protected Dictionary<string, List<string>> DependencyMap;
    
        protected BaseViewModel()
        {
            DependencyMap = new Dictionary<string, List<string>>();
    
            foreach (var property in GetType().GetProperties())
            {
                var attributes = property.GetCustomAttributes<DependsOnPropertyAttribute>();
                foreach (var dependsAttr in attributes)
                {
                    if (dependsAttr == null)
                        continue;
    
                    var dependence = dependsAttr.Dependence;
                    if (!DependencyMap.ContainsKey(dependence))
                        DependencyMap.Add(dependence, new List<string>());
                    DependencyMap[dependence].Add(property.Name);
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler == null)
                return;
    
            handler(this, new PropertyChangedEventArgs(propertyName));
    
            if (!DependencyMap.ContainsKey(propertyName))
                return;
    
            foreach (var dependentProperty in DependencyMap[propertyName])
            {
                handler(this, new PropertyChangedEventArgs(dependentProperty));
            }
        }
    }
    

    This now allows me to mark properties easily, like so:

    public int NormalProperty
    {
        get {return _model.modelProperty; }
        set 
        {
            _model.modelProperty = value;
            OnPropertyChanged();
        }
    }
    
    [DependsOnProperty(nameof(NormalProperty))]
    public int CalculatedProperty
    {
        get { return _model.modelProperty + 1; }
    }
    
    0 讨论(0)
提交回复
热议问题