我有一个Windows 8.1应用程序,其父视图和子视图模型具有以下关系
ParentViewModel
class ParentViewModel {
private double _parentAmount;
public double parentAmount
{
get { return _parentAmount; }
set
{
if (value != _parentAmount)
{
_parentAmount = value;
NotifyPropertyChanged("parentAmount");
}
}
}
private ObservableCollection<ChildViewModel> _children;
public ObservableCollection<ChildViewModel> children
{
get { return _children; }
set
{
if (value != _children)
{
_children = value;
NotifyPropertyChanged("children");
}
}
}
}
ChildViewModel
class ChildViewModel {
private double _ChildAmount;
public double ChildAmount
{
get { return _ChildAmount; }
set
{
if (value != _ChildAmount)
{
_ChildAmount = value;
NotifyPropertyChanged("ChildAmount");
}
}
}
}
在XAML中有TextBlock绑定到&#34; ParentAmount&#34;然后有一个ListView绑定到Observable集合&#34; Children&#34;。 ListView的Itemtemplate是一个带有TextBox的datatemplate,它与&#34; ChildAmount&#34;有双向绑定。用户可以修改子TextBox中的值
现在我的要求是当用户修改其中一个子金额时,使用其所有子金额的总和更新ParentAmount。我如何实现这一目标?
为了便于说明,我简化了上面粘贴的代码示例,ChildViewModel具有比可以看到的功能更多的功能,因此我不能用例如Double的List替换ChildViewModel的ObservableCollection。
如果有人能指出我正确的方向,我会很高兴。在此先感谢。
答案 0 :(得分:3)
只需要很少的添加,就可以了。 具体的更改是为ObservableCollection中的每个子对象添加属性更改处理程序。
请注意,这是一个粗略的例子,让你走上正确的轨道 - 我没有解开事件处理程序,我重新计算了来自孩子的任何变化的父母金额(即我没有检查它是否是更改了ChildAmount,这意味着您最终会采取比必要更多的操作。我还没有放入任何代码来处理对ObservableCollection内容的更改,所以如果添加新项目,它们就不会附加属性更改事件处理程序 - 这对你来说很简单。
请注意我使用BaseViewModel - 这只是一个很好的做法,它可以避免在每个需要它的类上重新实现INotifyPropertyChanged接口。
class ParentViewModel : BaseViewModel
{
private double _parentAmount;
public double parentAmount
{
get { return _parentAmount; }
set
{
if (value != _parentAmount)
{
_parentAmount = value;
NotifyPropertyChanged("parentAmount");
}
}
}
private ObservableCollection<ChildViewModel> _children;
public ObservableCollection<ChildViewModel> children
{
get { return _children; }
set
{
if (value != _children)
{
_children = value;
foreach (var child in _children)
child.PropertyChanged += ChildOnPropertyChanged;
NotifyPropertyChanged("children");
}
}
}
private void ChildOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
parentAmount = children.Sum(p => p.ChildAmount);
}
}
class ChildViewModel : BaseViewModel
{
private double _ChildAmount;
public double ChildAmount
{
get { return _ChildAmount; }
set
{
if (value != _ChildAmount)
{
_ChildAmount = value;
NotifyPropertyChanged("ChildAmount");
}
}
}
}
public class BaseViewModel : INotifyPropertyChanged
{
protected void NotifyPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
答案 1 :(得分:2)
更优雅的方法是使用Reactive Extensions。
首先你需要抓住
RX-主
来自程序包管理器控制台。
然后,创建一个static class
来托管使用Rx实现的扩展方法。像这样的东西 -
public static class Extensions
{
public static IObservable<T> OnPropertyChanges<T>(this T source, string propertyName)
where T : INotifyPropertyChanged
{
return Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
handler => handler.Invoke,
h => source.PropertyChanged += h,
h => source.PropertyChanged -= h)
.Where(p => p.EventArgs.PropertyName == propertyName)
.Select(_ => source);
}
}
最后,您可以在ParentViewModel
的构造函数(或任何必要的位置)中调用此方法。
// whenever the ChildAmount property of any ChildViewModel has changed, do something
Observable.Merge(children.Select(c => c.OnPropertyChanges("ChildAmount")))
.Subscribe((c) =>
{
// update your parent amount here
NotifyPropertyChanged("parentAmount");
});