关于ReactiveUi的另一个问题。我有一个ViewModel用于编辑表单。模型是ReactiveObject。我想只在发生对象更改时启用savecommand。我的尝试:
var canSaveCommand =
this.WhenAnyValue(vm => vm.CurrentClient)
.Where(client => client != null)
.Select(client =>
client.Changed
)
.Any();
但是当表单出现时,SaveCommand
已经启用。我的错误在哪里?
答案 0 :(得分:4)
您想使用Switch而不是SelectMany。 SelectMany不会取消订阅以前的客户。它将合并来自所有客户端的事件。在订阅下一个客户端之前切换取消订阅。
var canSaveCommand =
this.WhenAnyValue(vm => vm.CurrentClient)
.Where(client => client != null)
.Select(client =>
client.Changed
)
.Switch()
.Any();
例如,以下代码说明了这一点。我们假设我们有一个名为AudioChannel
的类,它会生成我们可以处理并发送给发言者的音频帧。
public class IAudioChannel {
public IObservable<AudioFrame> AudioFrameObservable {get;}
}
然后我们可能会有一个用户可以选择的音频节点列表,但我们只希望向扬声器发送最新的音频。下面的类使当前选择的音频节点可用作可观察的。
public class AudioListViewModel {
public class IObservable<IAudioChannel> CurrentAudioChannelObservable {get;}
}
现在考虑以下代码
AudioListViewModel viewModel;
viewModel
.CurrentAudioChannelObservable
.SelectMany(current=>current.AudioFrameObservable)
.Subscribe(frame=>frame.Play());
vs
AudioListViewModel viewModel;
viewModel
.CurrentAudioChannelObservable
.Select(current=>current.AudioFrameObservable)
.Switch()
.Subscribe(frame=>frame.Play());
在我们更改音频节点选择的第一个版本中,我们添加了越来越多的订阅。音频输出很快变成混乱频道的混乱。在第二个版本中,一次仅订阅一个频道,音频输出仅播放来自单个频道的输出。
许多人在开始使用RX时犯了这个错误。例如,我发现使用SelectMany而不是Switch的bug in the ReactiveUI framework。
ReactiveUI中有一种内置方式可以清晰地实现这一目标
实际上还有另一种方法可以达到你想要的效果,我会把它放在另一个答案中,只是为了向你展示如何使用ReactiveUI。
var canSaveCommand =
this
.WhenAnyObservable(vm => vm.CurrentClient.Changed)
.StartWith(false);
请注意,null不必明确处理,但您应该从 false 开始,以确保在没有observable可用的情况下存在值。
WhenAnyObservable与Rx运算符CombineLatest非常相似 它观察一个或多个可观察量,并允许您定义一个 根据每个人的最新价值进行投影。 WhenAnyObservable 与CombineLatest的不同之处在于它的参数是表达式, 而不是直接引用目标可观察量。的影响 这种差异是由WhenAnyObservable设置的手表不是 与当时存在的特定可观察实例相关联 订阅。也就是说,表达式指向的可观察量可以 稍后被替换,新的observable的结果仍然是 抓获。这可以派上用场的一个例子是视图 想要在viewmodel上观察一个observable,但是viewmodel可以 在视图的生命周期内被替换。而不是需要 每次更改视图模型后重新订阅目标observable, 你可以使用WhenAnyObservable指定&#39;路径&#39;观看。这个 允许您在视图中使用单个订阅,而不管它是什么 目标视图模型的生命周期。
答案 1 :(得分:-1)
尝试将您的选择更改为SelectMany。然后,这将为您提供一个Observable,表示要传递给Any的更改而不是Observable的Observable,以便将更改传递给Any。