Digital Camel
Digital Camel

Reputation: 305

Why is my property notification not triggering?

I have an hierarchy of classes. The pertinent bits are included below. I was expecting that when FilterCritetionInteger.CriterionValue is changed, via WPF binding, that I would get a notification in my FilterCriterionCollection. But, while the FilterCriterionInteger.CriterionValue setter is called, the FilterCriterionCollection.Criterion_PropertyChanged method is never called.

Apparently I am misunderstanding something, or have something connected incorrectly. I'm just not finding it. Why is my notification not happening? (Please let me know if there is more context needed, anywhere.)

ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged(string propertyName)
  {
    PropertyChangedEventHandler pcHandler = this.PropertyChanged;

    if (pcHandler != null)
    {
      PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName);
      pcHandler(this, args);
     }
  }  
}

FilterCriterionBase

public abstract class FilterCriterionBase : ViewModelBase
{
  public abstract bool IsValid { get; }
}

FilterCriterionInteger

public class FilterCriterionInteger : FilterCriterionBase
{
  private string _criterionValue = "0";
  public string CriterionValue
  {
    get { return _criterionValue; }
    set
    {
      _criterionValue = value;
      OnPropertyChanged("IsValid");
    }
  }

  public int? MaxValue { get; private set; } = null;

  public override bool IsValid
  {
    get
    {
      if (int.TryParse(_criterionValue, out int i))
      {
        if (MaxValue.HasValue && (i > MaxValue)) return false;
      }
      else
      {
        return false;
      }

      return true;
    }
  }
}

FilterCriterionCollection

public class FilterCriteriaCollection : ViewModelBase
{
  public FilterCriteriaCollection()
  {
    Criteria.CollectionChanged += Criteria_CollectionChanged;
  }

  ~FilterCriteriaCollection()
  {
    Criteria.CollectionChanged -= Criteria_CollectionChanged;
  }

  public ObservableCollection<FilterCriterionBase> Criteria { get; private set; } = new ObservableCollection<FilterCriterionBase>();

  private void Criteria_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
  {
    switch (e.Action)
    {
      case NotifyCollectionChangedAction.Add:
        foreach (FilterCriterionBase fb in e.NewItems)
        {
          fb.PropertyChanged += Criterion_PropertyChanged;
        }
        break;

      case NotifyCollectionChangedAction.Remove:
        foreach (FilterCriterionBase fb in e.NewItems)
        {
          fb.PropertyChanged -= Criterion_PropertyChanged;
        }
        break;
    }
  }

  private bool _isValid;
  public bool IsValid
  {
    get { return _isValid; }
    private set { _isValid = value; OnPropertyChanged("IsValid"); }
  }

  private void Criterion_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
  {
    using (FilterCriterionBase criterion = sender as FilterCriterionBase)
    {
      switch (e.PropertyName)
      {
        case "IsValid":
          {
            bool isvalid = true;

            foreach(FilterCriterionBase fcb in Criteria)
            {
              isvalid = fcb.IsValid;
              if (!isvalid) break;
            }

            IsValid = isvalid;
            break;
          }
      }
    }
  }
}

Upvotes: 0

Views: 133

Answers (1)

Digital Camel
Digital Camel

Reputation: 305

So, as it turns out, I am a moron. The code, above, does need a little tweaking but it is, in general, sound. My primary issue was that I had some leftover code, in my testing sandbox, from testing some JSON serialization/deserialization. I realized, after much head banging, that I was sending deserialized objects that had lost their event notification context and, therefore, were no longer in the loop.

Would it be proper protocol to just delete this post, since it doesn't really require an answer beyond double checking your inputs...?

Upvotes: 1

Related Questions