观察两个响应式列表的ItemChanged事件

3

我有一个ViewModel,我想监听两个响应式列表(Payments和AccountPayments)中的项目更改。这些列表已被实例化并启用了ChangeTrackingEnabled:

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);

但这段代码无法编译通过。 有没有办法实现我想要做的事情?非常感谢您的帮助。

1个回答

3
第一种方法行不通,因为它观察属性变化,而 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,因为它会重新编写该表达式以观察属性更改,以确保它具有最新的可观察对象。如果既不会更改Payments也不会更改AccountPayments(即它们是只读的),则可以完全省略WhenAnyObservable

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

谢谢你的帮助,Charles。事实上,我漏掉了右括号(多么尴尬),但是编译错误仍然存在。在发现我的第二个片段是正确的方法后,我深入挖掘了一下。原来问题是我在问题中没有提到的东西。这两个列表包含两种不同的类型。AccountPayment是一个不同于Payment类的类。有点傻。再次感谢您的代码审查和指引。 - Stuart
@StuartMiller ... 这就是我的答案。虽然我承认当我最初回答时错过了它,也许你还没有看到编辑! - Charles Mager
哦,我没有看到你的编辑。那正是我所需要的,而且我不知道。非常感谢你的帮助。 - Stuart
刚刚测试了一下,又遇到了另一个问题。我收到了一个运行时异常,类型为“System.NotSupportedException”,显示“仅支持使用常量的索引表达式”。当我尝试返回Unit.Default时似乎会出现这种情况。 - Stuart
@StuartMiller 哦,你说得对。WhenAny设置了一个属性更改监听器来跟踪其中表达式的变化,因此不支持进行任何花哨的操作。我会更新的。 - Charles Mager
Charles,你的代码运行得非常好。非常感谢你的帮助!我已经更正了我的原始帖子,包括在我的选择结尾处缺失的右括号。 - Stuart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接