间接财产通知

发布于 2024-08-29 14:52:17 字数 2599 浏览 5 评论 0原文

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

场景:

我有两个属性,第一个是一个名为 HoldingObject 的对象,第二个是一个名为 IsHoldingObject 的布尔值,如果 HoldingObject == null 则为 false,否则为 true。我只是想知道 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) - 通过从 HoldingObject 属性将其设置为 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
}

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

谢谢!

this question might look a little trivial, but it might not be. I'm just wondering which of the following two cases is better for indirect property notification, or perhaps there is an even better way.

The scenario:

I have two properties, the first one is an object called HoldingObject, the second one is a boolean called IsHoldingObject, which is false if HoldingObject == null, otherwise it's true. I'm just wondering what is the best notification mechanism for IsHoldingObject:

Case (A) - Notify IsHoldingObject changed from the HoldingObject 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
}

Case (B) - Notify IsHoldingObject changed from the IsHoldingObject directly, by setting it to false or true from HoldingObject property:

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
}

I personally lean to the first one because it requires less code, but I'm not sure how recommendable it is to do that. Let me know if there is another (better) way.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如若梦似彩虹 2024-09-05 14:52:17

我几乎总是选择第二个。这样,负责设置给定属性的所有代码都位于一个位置。在这种特殊情况下,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"); }
}

I almost always go for the second one. That way, all the code responsible for setting a given property is in one place. In this particular case, the IsHoldingObject property is entirely dependent on the HoldingObject property, so it may not apply. But in general, it may be less code now, but what happens if you need to update that property from somewhere else later on?

The pain you are having (the verbosity of the code) can be easily mitigated by a helper method that is used to set properties in a view model (this can live in a base class):

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

    return false;
}

Your properties then become:

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"); }
}
过潦 2024-09-05 14:52:17

在大多数情况下这并不重要。让我们看看

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

所以我想这取决于什么对你来说更具可读性。我更喜欢“每次都计算”。然后使用这个 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); } }
}

In most scenarios it does not matter. Lets look at the options

  • Calculate each time. So here you are consuming CPU each time the UI request the value. But considering how much CPU it takes each time the UI would need to be requesting the value 100s per second before your would even notice a hit. I doubt your UI would require this.
  • Store the value. Here you are consuming memory. Again this is a non issue unless you store many large objects.

So I guess it comes down to what ever is more readable for you. I prefer "Calculating each time". Then using this http://code.google.com/p/notifypropertyweaver/ it allows me to write this code

public class NotifyingClass1 : INotifyPropertyChanged
{
    public object HoldingObject { get; set; }

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

    public event PropertyChangedEventHandler PropertyChanged;
}

And have this compiled to the assembly (ie the dependency is derived)

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); } }
}
以可爱出名 2024-09-05 14:52:17

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

我很好奇其他意见。

问候

interesting idea. I think, I would have used the BindingConverter approach, which convertes HoldingObject to the value you like.

I'm curious about other opinions.

Regards

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文