llo*_*mas 15 c# wpf binding mvvm 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
}
我有一个Address类:
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
}
我有一个ViewModel:
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" );
           }
     }
}
我有一个视图,其中包含以下行:
<TextBox  Text="{Binding Person.Name, Mode=TwoWay,   
    UpdateSourceTrigger=PropertyChanged />
<TextBox  Text="{Binding Person.Address.StreetOne, Mode=TwoWay,   
    UpdateSourceTrigger=PropertyChanged />
视图加载时,两个值都显示在文本框中.
将OnPropertyChanged( "Person" )在MyViewModel 中触发对第一个文本框的更改.大.
对MyViewModel内部的第二个文本框的更改("Person.Address.StreetOne")不会触发OnPropertyChanged( "Person" ).这意味着它不会调用Person对象的SET方法.不是很好.有趣的是,调用了Address类中的StreetOne的SET方法.
如何在Person.Address.StreetOne更改时调用ViewModel中的Person对象的SET方法?
我是否需要展平我的数据,以便SteetOne在Person内部而不是Address?
谢谢!
And*_*lon 15
虽然向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");
        }
  }
现在,更改通知将从地址传播到人员.
编辑:将处理程序移动到c#7本地函数.
如果要调用viewmodel SET,可以创建一个street属性
public class MyViewModel
{
  //constructor and other stuff here
  public string Street{
    get { return this.Person.PrimaryAddress.StreetOne; }
    set {
       if ( this.Person.PrimaryAddress.StreetOne!= value ) {
         this.Person.PrimaryAddress.StreetOne = value;
         OnPropertyChanged( "Street" );
       }
   }
 }
XAML
<TextBox  Text="{Binding Street, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged />
但这种解决方案有其缺点.我在我的项目中与Reeds一起回答
当Person.Address.StreetOne更改时,如何获取ViewModel内部的Person对象的SET方法?
为什么要这样做?它不是必需的-您只需要StreetOne触发属性更改事件即可。
我是否需要拼合数据,以便SteetOne位于Person内部而不是Address?
如果您想实际触发该事件,则无需使其变平(尽管这是一个选择)。您可以在Person类中订阅Address的PropertyChanged事件,并在Person更改时在“ Address”事件中引发该事件。但是,这不是必需的。