【问题标题】:Why is my property notification not triggering?为什么我的财产通知没有触发?
【发布时间】:2019-01-26 23:24:58
【问题描述】:

我有一个类层次结构。相关位包括在下面。我期待当通过 WPF 绑定更改 FilterCritetionInteger.CriterionValue 时,我会在我的 FilterCriterionCollection 中收到通知。但是,在调用 FilterCriterionInteger.CriterionValue 设置器时,永远不会调用 FilterCriterionCollection.Criterion_PropertyChanged 方法。

显然我误解了某些东西,或者连接不正确。我只是没有找到它。为什么我的通知没有发生? (如果需要更多上下文,请告诉我。)

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;
          }
      }
    }
  }
}

【问题讨论】:

  • 字符串显示“isValid”但在 CriterionValue 属性中
  • @Charlie - 这是一个触发“IsValid”属性重新评估的调用。带有大写“I”的“IsValid”是属性的公共名称。我看不出有什么问题。你能说得更具体点吗?
  • 也尝试添加:OnPropertyChanged("CriterionValue")。重新评估没问题,但如果你绑定 CriterionValue,那么 CriterionValue 必须有一个 changedevent。
  • 更改来自 WPF 绑定。在我的场景中,更改永远不会在内部发生,因此没有人需要通知。一旦用户更改了值,我只需要重新评估有效性。
  • @DigitalCamel 附带说明:为什么你有using 声明?你打算在你的事件处理程序中处理事件发送者吗?这看起来不对。

标签: c# inotifypropertychanged


【解决方案1】:

所以,事实证明,我是个白痴。上面的代码确实需要一些调整,但总的来说,它是合理的。我的主要问题是,在我的测试沙箱中,我有一些剩余代码,来自测试一些 JSON 序列化/反序列化。经过多次头疼后,我意识到我正在发送已丢失事件通知上下文的反序列化对象,因此不再处于循环中。

删除此帖子是否是正确的协议,因为除了仔细检查您的输入之外,它实际上不需要答案...?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多