【问题标题】:WPF Notify PropertyChanged for a Get PropertyWPF 通知 PropertyChanged 获取属性
【发布时间】:2014-03-13 15:24:07
【问题描述】:

我使用CallerMemberName 实现了INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
 if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

因此,这可以在任何属性的设置器中调用 - OnPropertyChanged(),它会在设置属性时通知属性更改事件。对于仅作为 getter 的属性而言,情况并非如此。例如,

private DateTime _dob;
public DateTime DateOfBirth
{
    get
    {
        return _dob;
    }
    private set
    {
        _dob = value;
        OnPropertyChanged();
        OnPropertyChanged("Age");
    }
}

public int Age
{
    get
    {
        return DateTime.Today.Year - _dob.Year;
    }
}

OnPropertyChanged() 适用于 DateOfBirth,但要通知 Age 已更改,我应该记得在 DateOfBirth 的设置器中调用 OnPropertyChanged("Age")。我觉得这使得代码随着时间的推移难以维护。如果一个新属性依赖于年龄,那也需要在 DateOfBirth 的设置器中通知。有没有更好的方法可以在不调用 OnPropertyChanged("Age") 的情况下做到这一点?

【问题讨论】:

  • 这个OnPropertyChanged() 只适用于setter 吗?如果没有,您可以尝试将return 语句放在try-finally 中,然后在那里调用OnPropertyChanged()
  • 能否详细说明。 OnPropertyChanged 始终有效,但只有在有人更改值时才应通知它。因此,将它放在 setter 中是有意义的。我不明白我在哪里以及为什么需要最后尝试?
  • 如果您不想调用OnPropertyChanged("Age"),在设置DOB值时将“年龄”作为参数,在Age's get上您可以返回try内的值,在finally 内,您可以调用OnPropertyChanged(),不带参数。
  • 这行不通。我使用 OnPropertyChanged 的​​原因是,如果有人更改 DOB,OnPropertyChanged 将触发 UI 访问 Get of Age。如果我在 Get of Age 中移动 OnpropertyChanged,它将进入无限循环,一次又一次地尝试访问 get 并获得更改的通知。
  • Guilherme 的 cmets 完全没有意义。属性通知显然需要在设置、不获取和尝试/最终实现任何目标时进行(除了触发事件,即使 getter 中有异常,这很奇怪)。

标签: c# wpf inotifypropertychanged callermembername


【解决方案1】:

只要您的从属属性在同一个类中,您就可以使用 Poma 的方法,但如果从属属性在不同的类中,则使用该方法会变得更加困难。

在我看来,在概念上正确的做法是添加一个 PropertyChanged 侦听器。

在这种情况下,就像

在构造函数中:

this.PropertyChanged += new PropertyChangedEventHandler(SubPropertyChanged);

外面:

private void SubPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "DateOfBirth")
    {
       OnPropertyChanged("Age");
    }
}

如果您在完全不同的地方有一个依赖属性,并且如果您不能再更改您的源类,这也可以工作。

【讨论】:

    【解决方案2】:

    一种方法是定义您的属性并在OnPropertyChanged 中进行一些反射以通知所有相关属性。您可能希望缓存属性以仅在类初始化程序中使用反射,因为反射非常慢。

    private DateTime _dob;
    public DateTime DateOfBirth
    {
        get
        {
            return _dob;
        }
        private set
        {
            _dob = value;
            OnPropertyChanged();
        }
    }
    
    [DependsOnProperty("DateOfBirth")]
    public int Age
    {
        get
        {
            return DateTime.Today.Year - _dob.Year;
        }
    }
    

    【讨论】:

    • DependsOnProperty 不是来自框架吗?
    • @ElMac 在谷歌中找不到它。但是无论如何都有命名空间可以避免冲突。
    • 什么是属性DependsOnProperty? OP必须实施什么,而您只是举个例子?
    猜你喜欢
    • 2010-10-10
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    相关资源
    最近更新 更多