2017-03-06 49 views
0

我们有一个有孩子集合的父类。这两个类都使用Template10支持更改通知。更改通知在每个类中的作用(即当我们在同一个类中更新一个属性时)如下所示,但是我们无法触发孩子父母的更改通知。RaisePropertyChanged不通知家长

public class ParentViewModel : ViewModelBase 
{ 
    public string ParentString { get } 
    public decimal? Net { get { return Total/(1 + TaxRate/100); } }   
    public decimal? Tax { get { return Total - Net; } } 
    decimal? _Total = default(decimal?); 
    public decimal? Total 
    { 
     get 
     { 
      return _Total; 
     } 
     set 
     { 
      Set(ref _Total, value); 
      RaisePropertyChanged(nameof(Net)); 
      RaisePropertyChanged(nameof(Tax)); 
     } 
    } 

    public ObservableCollection<ChildViewModel> MyChildren { get; set; } 

我们发现,我们能够使用RaisePropertyChangedParentViewModel

Net { get { return Total/(1 + TaxRate/100); } } 

Tax { get { return Total - Net; } } 

ChildViewModel我们ChildString。我们想要通知ParentStringChildString的更改。

public class ChildViewModel : ViewModelBase 
{ 
    ParentViewModel MyParent { get; set; } 
    string _ChildString = default(string); 
    public string ChildString 
    { 
     get 
     { 
      return _ChildString; 
     } 
     set 
     { 
      Set(ref _ChildString, value); 
      RaisePropertyChanged(nameof(this.MyParent.ParentString)); 
     } 
    } 

但是ParentString未更新。当ChildString更新时,我们如何强制更新ParentString

+0

其中'this.MyParent'分配?也许[这个问题](http://stackoverflow.com/questions/1427471/observablecollection-not-noticing-when-item-in-it-changes-even-with-inotifypropo)帮助 –

+0

@雷洋MyParent分配通过任何方法创建一个ChildViewModel的实例。谢谢你的链接。被接受的答案对我们来说是诀窍。 – Vague

回答

1

无论nameof是什么意思,当您调用ChildViewModel.RaisePropertyChanged时,您会在子视图模型上触发事件。

nameof运算符不能“更改”事件源。您需要一种方式来以某种方式激发父母PropertyChanged。最简单的方法就是让合适的方法在ParentViewModel

public void RaiseParentStringChanged() 
{ 
    RaisePropertyChanged(nameof(ParentString)); 
} 

,并从孩子叫它:

public string ChildString 
{ 
    get 
    { 
     return _ChildString; 
    } 
    set 
    { 
     Set(ref _ChildString, value); 

     // assuming, that parent is assigned at this point 
     MyParent.RaiseParentStringChanged(); 
    } 
} 

但它会是不错的,从孩子扔掉父母,如果ParentString改变是唯一的有理由带来这种依赖性。

由于MyChildren是可观察的集合,因此您可以在其CollectionChanged事件中订阅。当添加新孩子时,您可以订阅其PropertyChanged,并注意ChildString更改以提出适当的父母事件。

这件事情是这样的:

// non-related code is omitted 
public class ParentViewModel: ViewModelBase 
{ 
    private ObservableCollection<ChildViewModel> children; 

    public string ParentString { get; } 

    // don't do collection properties on view models 
    // as get-set ones, unless you know exactly what are you doing; 
    // usually you don't need to set them explicitly from outside 
    public ObservableCollection<ChildViewModel> MyChildren 
    { 
     get 
     { 
      if (children == null) 
      { 
       children = new ObservableCollection<ChildViewModel>(); 
       children.CollectionChanged += ChildrenChanged; 
      } 
      return children; 
     } 
    } 

    private void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     // assuming, that only two actions ("add" and "remove") are available; 
     // if you really need to nadle "reset" and "replace", add appropriate code; 
     // note, that "reset" doesn't provide acceess to removed items 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
       ((ChildViewModel)e.NewItems[0]).PropertyChanged += ChildPropertyChanged; 
       break; 
      case NotifyCollectionChangedAction.Remove: 
       ((ChildViewModel)e.OldItems[0]).PropertyChanged -= ChildPropertyChanged; 
       break; 
     } 
    } 

    private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == nameof(ChildViewModel.ChildString)) 
     { 
      RaisePropertyChanged(nameof(ParentString)); 
     } 
    } 
} 
+0

谢谢@丹尼斯。你能否给我一个如何订阅儿童收藏变化的例子? – Vague

+0

@Vague:我已经更新了答案。 – Dennis