【问题标题】:Indirect property notification间接财产通知
【发布时间】:2010-04-19 20:18:05
【问题描述】:

这个问题可能看起来有点微不足道,但可能并非如此。我只是想知道以下两种情况中哪一种更适合间接财产通知,或者也许有更好的方法。

场景:

我有两个属性,第一个是一个叫做HoldingObject的对象,第二个是一个叫做IsHoldingObject的布尔值,如果HoldingObject == null则为假,否则为真。我只是想知道 IsHoldingObject 的最佳通知机制是什么:

案例 (A) - 通知 IsHoldingObject 从 HoldingObject 属性更改:

public class NotifyingClass1 : INotifyPropertyChanged
{
    private object _holdingObject;
    public object HoldingObject
    {
        get { return _holdingObject; }
        set
        {
            if (_holdingObject != value)
            {
                _holdingObject = value;
                NotifyPropertyChanged("HoldingObject");
                // Notify from the property that is being checked
                NotifyPropertyChanged("IsHoldingObject");
            }
        }
    }

    public bool IsHoldingObject { get { return this.HoldingObject == null; } }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

案例 (B) - 通知 IsHoldingObject 直接从 IsHoldingObject 更改,通过将 HoldingObject 属性设置为 false 或 true:

public class NotifyingClass2 : INotifyPropertyChanged
{
    private object _holdingObject;
    public object HoldingObject
    {
        get { return _holdingObject; }
        set
        {
            if (_holdingObject != value)
            {
                _holdingObject = value;
                NotifyPropertyChanged("HoldingObject");

                // 1) Set the property here
                this.IsHoldingObject = _holdingObject != null;
            }
        }
    }

    private bool _isHoldingObject;
    public bool IsHoldingObject
    {
        get { return _isHoldingObject; }
        set
        {
            if (_isHoldingObject != value)
            {
                _isHoldingObject = value;

                // 2) Notify directly from the property
                NotifyPropertyChanged("IsHoldingObject");
            }
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

我个人倾向于第一个,因为它需要的代码更少,但我不确定这样做是否值得推荐。如果有其他(更好的)方法,请告诉我。

谢谢!

【问题讨论】:

    标签: .net wpf inotifypropertychanged


    【解决方案1】:

    我几乎总是选择第二个。这样,负责设置给定属性的所有代码都在一个地方。在这种特殊情况下,IsHoldingObject 属性完全依赖于 HoldingObject 属性,因此它可能不适用。但总的来说,现在可能会减少代码,但是如果您以后需要从其他地方更新该属性会发生什么?

    您所遇到的痛苦(代码的冗长)可以通过用于在视图模型中设置属性的辅助方法轻松缓解(这可以存在于基类中):

    protected bool SetValue<T>(ref T field, T value, string propertyName)
    {
        if (!Equals(field, value))
        {
            field = value;
            NotifyPropertyChanged(propertyName);
            return true;
        }
    
        return false;
    }
    

    然后您的属性变为:

    private object _holdingObject;
    public object HoldingObject
    {
        get { return _holdingObject; }
        set
        {
            if (SetValue(ref _holdingObject, value, "HoldingObject"))            
                this.IsHoldingObject = _holdingObject != null;
        }
    }
    
    private bool _isHoldingObject;
    public bool IsHoldingObject
    {
        get { return _isHoldingObject; }
        private set { SetValue(ref _isHoldingObject, value, "IsHoldingObject"); }
    }
    

    【讨论】:

      【解决方案2】:

      在大多数情况下,这无关紧要。让我们看看选项

      • 每次计算。因此,每次 UI 请求该值时,您都在消耗 CPU。但是考虑到每次 UI 需要每秒请求 100 秒的值时需要多少 CPU,您才会注意到命中。我怀疑你的 UI 会需要这个。
      • 存储值。在这里,您正在消耗内存。同样,除非您存储许多大型对象,否则这不是问题。

      所以我想这归结为对你来说更具可读性。我更喜欢“每次计算”。然后使用这个http://code.google.com/p/notifypropertyweaver/ 它允许我编写这段代码

      public class NotifyingClass1 : INotifyPropertyChanged
      {
          public object HoldingObject { get; set; }
      
          public bool IsHoldingObject { get { return HoldingObject == null; } }
      
          public event PropertyChangedEventHandler PropertyChanged;
      }
      

      并将其编译到程序集中(即派生依赖项)

      public class NotifyingClass1 : INotifyPropertyChanged
      {
          private object holdingObject;
      
          public event PropertyChangedEventHandler PropertyChanged;
      
          public virtual void OnPropertyChanged(string propertyName)
          {
              var propertyChanged = PropertyChanged;
              if (propertyChanged != null)
              {
                  propertyChanged(this, new PropertyChangedEventArgs(propertyName));
              }
          }
      
          public object HoldingObject
          {
              get { return holdingObject; }
              set
              {
                  if (holdingObject !=value)
                  {
                      holdingObject = value;
                      OnPropertyChanged("HoldingObject");
                      OnPropertyChanged("IsHoldingObject");
                  }
              }
          }
      
          public bool IsHoldingObject { get { return (HoldingObject == null); } }
      }
      

      【讨论】:

        【解决方案3】:

        有趣的想法。我想,我会使用 BindingConverter 方法,它将 HoldingObject 转换为您喜欢的值。

        我很好奇其他意见。

        问候

        【讨论】:

          猜你喜欢
          • 2014-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多