【发布时间】:2022-01-12 00:19:07
【问题描述】:
我有一个具有属性 A 的视图模型。属性 A 属于具有属性 B 的类型。现在我想在我的视图模型的构造函数中订阅属性 B 的任何直接更改。我的意思是“直接”我只想在属性 A 的当前值的属性 B 发生变化时运行我的订阅,而不是在属性 A 的值发生变化时运行。
现在我有这样的东西:
this.WhenAnyValue(x => x.A.B)
.Subscribe(b => DoSomethingWithB(b));
但是,如果属性 A 的值发生变化,这当然也会执行DoSomethingWithB。我已经尝试过是否可以使用 WhenAnyObservable 或 Switch 扩展方法,但到目前为止我无法弄清楚它的外观。
编辑:
由于我不知道我最初的问题是否足够清楚,我现在添加了一个工作示例,涵盖了我需要考虑的所有情况。为简单起见,属性 B 的类型为 int,我在 TypeA 中添加了一个 ID 属性以便能够区分它们。
using ReactiveUI;
using System;
using System.ComponentModel;
namespace ObservePropertyTail
{
class Program
{
static void Main(string[] args)
{
ViewModel vm = new ViewModel();
// Pings but should not because A was changed.
vm.A = new TypeA(1) { B = 1 };
// Pings which is the desired behavior.
vm.A.B = 2;
// Does not ping (by chance because value of B remains the
// same although A is changed) which is the desired behavior.
vm.A = new TypeA(2) { B = 2 };
// Pings but should not because A was changed.
vm.A = new TypeA(3) { B = 3 };
// Should not ping and does not.
vm.A = null;
// Should not ping but does.
vm.A = new TypeA(4) { B = 4 };
// Should ping and does.
vm.A.B = 3;
}
}
class ViewModel : INotifyPropertyChanged
{
private TypeA a;
public ViewModel()
{
this.WhenAnyValue(x => x.A.B)
.Subscribe(b => Console.WriteLine($"Ping: A = {A.ID}, b = {b}"));
}
public TypeA A
{
get => a;
set
{
if (a != value)
{
a = value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(A)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
class TypeA : INotifyPropertyChanged
{
private int b;
public TypeA(int id) => ID = id;
public int ID { get; }
public int B
{
get => b;
set
{
if (b != value)
{
b = value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(B)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
输出:
Ping: A = 1, b = 1
Ping: A = 1, b = 2
Ping: A = 3, b = 3
Ping: A = 4, b = 4
Ping: A = 4, b = 3
【问题讨论】:
-
可以选择使用
DistinctUntilChanged()吗? -
“但是,如果属性 A 的值发生变化,这当然也会执行 DoSomethingWithB” - 不,它不应该。
-
我现在在我的问题中添加了一个工作示例,以证明它的行为不符合预期。明确期望的行为是什么。
-
在您的 working 示例中。为什么不应该在第一种情况下不进行 ping 操作? B 从 0 更改为 1。第二个 ping 也是,因为它从 1 更改为 2。第三个不 ping,因为它没有更改 B(仍然是 2),在最后一种情况下,您同时更改了 A 和 B (B 从 2 到 3)。所以恕我直言,它按预期工作。每当 B 更改(无论 A 是什么)时,都会调用您的订阅。
-
嗯,看来我还是误会了:我知道我的演示应用程序的行为是 Reactive Extensions 和 ReactiveUI 的开发人员所期望的,所以并不是我认为我发现了一个错误.我的实际问题是是否有过滤器运算符或不同的方法来实现我的演示代码中描述的行为。
DistinceUntilChanged朝着正确的方向前进,我尝试使用接受IEqualityComparer的自定义实现但没有成功的重载。
标签: c# system.reactive reactiveui