间接财产通知

时间:2010-04-19 20:18:06

标签: .net wpf inotifypropertychanged

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

情景:

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

案例(A) - 通知IsHoldingObject已从HoldObject proeperty更改:

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) - 通过从HoldObject属性将其设置为false或true,通知IsHoldingObject直接从IsHoldingObject更改:

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
}

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

谢谢!

3 个答案:

答案 0 :(得分: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"); }
}

答案 1 :(得分:1)

在大多数情况下都没关系。让我们看一下选项

  • 每次计算。因此,每次UI请求值时,您都在消耗CPU。但是考虑到每次UI需要在你甚至注意到命中之前请求每秒100秒的CPU需要多少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); } }
}

答案 2 :(得分:0)

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

我对其他意见感到好奇。

此致