观察两个反应分子上的ItemChanged

本文关键字:ItemChanged 两个 观察 | 更新日期: 2023-09-27 17:51:15

我有一个ViewModel,我想在其中监听两个reactivelist, Payments和AccountPayments中项目的更改。列表被实例化,并且ChangeTrackingEnabled被设置为true:

this.Payments = new ReactiveList<transaction.PaymentViewModel>();
this.Payments.ChangeTrackingEnabled = true;`
this.AccountPayments = new ReactiveList<AccountPaymentViewModel>();
this.AccountPayments.ChangeTrackingEnabled = true;`
然后,在我的ViewModel中定义,我有一个ObservableAsPropertyHelper只读属性:
readonly ObservableAsPropertyHelper<decimal> _totalPayments;
public decimal TotalPayments { get { return _totalPayments.Value; } }

我的目的是设置TotalPayments每当这些项目在两个列表中改变。我尝试使用WhenAny:

this.WhenAny(vm => vm.Payments.ItemChanged,
            vm => vm.AccountPayments.ItemChanged,
            (a, b) => a.Sender.Payments
                .Where(x => x.Amount.HasValue).Sum(x => x.Amount.Value)
                + b.Sender.AccountPayments
                .Where(x => x.Amount.HasValue).Sum(x => x.Amount.Value))
            .ToProperty(this, vm => vm.TotalPayments, out _totalPayments);

虽然编译得很好,但它似乎没有捕捉到更改。我还尝试使用WhenAnyObservable:

this.WhenAnyObservable(
            vm => vm.Payments.ItemChanged,
            vm => vm.AccountPayments.ItemChanged)
            .Select(_ =>
                this.Payments.Where(x => x.Amount.HasValue)
                    .Sum(x => x.Amount.Value)
                + this.AccountPayments.Where(x => x.Amount.HasValue)
                    .Sum(x => x.Amount.Value))
            .ToProperty(this, vm => vm.TotalPayments, out _totalPayments);

但是这不会编译。有什么方法可以完成我想做的事情吗?

观察两个反应分子上的ItemChanged

第一个不工作,因为它观察属性的变化和ItemChanged本身不会改变,它是一个可观察对象。

第二个是非常正确的,但需要一点修改。WhenAnyObservable要求所有的观测对象为同一类型。由于您对实际结果不感兴趣,您可以选择Unit并合并两者:

this.WhenAnyObservable(a => a.Payments.ItemChanged).Select(_ => Unit.Default)
    .Merge(this.WhenAnyObservable(a => a.AccountPayments.ItemChanged).Select(_ => Unit.Default));

你不能在WhenAnyObservable中选择Unit.Default,因为它会重写这个表达式来观察属性的变化,以确保它有最新的可观察对象。如果PaymentsAccountPayments都不会改变(即它们是只读的),您可以完全省略WhenAnyObservable:

Payments.ItemChanged.Select(_ => Unit.Default)
    .Merge(AccountPayments.ItemChanged.Select(_ => Unit.Default));