c# - 为嵌套属性实现 INotifyPropertyChanged

标签 c# wpf mvvm binding inotifypropertychanged

我有一个 Person 类:

public class Person : INotifyPropertyChanged
{
     private string _name;
     public string Name{
     get { return _name; }
     set {
           if ( _name != value ) {
             _name = value;
             OnPropertyChanged( "Name" );
           }
     }

     private Address _primaryAddress;
     public Address PrimaryAddress {
     get { return _primaryAddress; }
     set {
           if ( _primaryAddress != value ) {
             _primaryAddress = value;
             OnPropertyChanged( "PrimaryAddress" );
           }
     }

     //OnPropertyChanged code goes here
}

我有一个地址类:

public class Address : INotifyPropertyChanged
{
     private string _streetone;
     public string StreetOne{
     get { return _streetone; }
     set {
           if ( _streetone != value ) {
             _streetone = value;
             OnPropertyChanged( "StreetOne" );
           }
     }

     //Other fields here

     //OnPropertyChanged code goes here
}

我有一个 View 模型:

public class MyViewModel
{
   //constructor and other stuff here

     private Person _person;
     public Person Person{
     get { return _person; }
     set {
           if ( _person != value ) {
             _person = value;
             OnPropertyChanged( "Person" );
           }
     }

}

我有一个包含以下几行的 View :

<TextBox  Text="{Binding Person.Name, Mode=TwoWay,   
    UpdateSourceTrigger=PropertyChanged />

<TextBox  Text="{Binding Person.Address.StreetOne, Mode=TwoWay,   
    UpdateSourceTrigger=PropertyChanged />

当 View 加载时,这两个值都显示在文本框中。

对第一个文本框的更改将触发 MyViewModel 中的 OnPropertyChanged( "Person")。太好了。

对第二个文本框 ("Person.Address.StreetOne") 的更改不会触发 MyViewModel 内的 OnPropertyChanged( "Person")。这意味着它不调用 Person 对象的 SET 方法。不是很好。有趣的是调用了 Address 类中 StreetOne 的 SET 方法。

如何在 Person.Address.StreetOne 更改时调用 ViewModel 中 Person 对象的 SET 方法???

我是否需要展平我的数据,以便 SteetOne 在 Person 而不是 Address 中?

谢谢!

最佳答案

虽然向 ViewModel 添加“传递”属性是一个很好的解决方案,但它很快就会变得站不住脚。标准的替代方法是传播更改,如下所示:

  public Address PrimaryAddress {
     get => _primaryAddress;
     set {
           if ( _primaryAddress != value ) 
           {
             //Clean-up old event handler:
             if(_primaryAddress != null)
               _primaryAddress.PropertyChanged -= AddressChanged;

             _primaryAddress = value;

             if (_primaryAddress != null)
               _primaryAddress.PropertyChanged += AddressChanged;

             OnPropertyChanged( "PrimaryAddress" );
           }

           void AddressChanged(object sender, PropertyChangedEventArgs args) 
               => OnPropertyChanged("PrimaryAddress");
        }
  }

现在更改通知从 Address 传播到 person。

编辑:将处理程序移至 c# 7 本地函数。

关于c# - 为嵌套属性实现 INotifyPropertyChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11870069/

相关文章:

c# - 使用AT命令

wpf - 无法在 Internet Explorer 11 上运行 Xbap 应用程序

c# - 如何使用 ProgressBar 更新正确实现 BackgroundWorker?

c# - 跨平台应用程序 WPF、ASP.NET、Silverlight、WP7、XAML

ios - 如何使用 MVVM 和 RxSwift 编辑/删除 UICollectionView 单元格

c# - ReactiveUI ViewModel (ReactiveObject) 异步任务的取消

c# - 在 MVVM 中以编程方式更改 WPF 窗口大小

c# - 修改 ASP.NET 成员架构

c# - "large"滚动时数据集崩溃 Gridview。 Win32错误

c# - DropDownList 未按预期运行