我们有一个父类,它有一个子集合。这两个类都支持使用Template10进行更改通知。更改通知在每个类中起作用(即当我们更新同一类中的属性时),如下所示,但是我们无法触发来自子项的父级的更改通知。
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; }
我们发现我们可以使用RaisePropertyChanged
中的ParentViewModel
来解雇
Net { get { return Total / (1 + TaxRate / 100); } }
和
Tax { get { return Total - Net; } }
在ChildViewModel
我们ChildString
。我们希望将ParentString
的更改通知ChildString
。
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
没有更新。 ParentString
更新时,我们如何强制ChildString
更新?
答案 0 :(得分:1)
无论nameof
参数如何,当您调用ChildViewModel.RaisePropertyChanged
时,都会在子视图模型上触发事件。
nameof
运营商无法改变&#34;事件来源。你需要一种以某种方式解雇父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));
}
}
}