Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 如何正确订阅已更改的反应对象序列?_Linq_System.reactive_Reactive Programming_Reactiveui - Fatal编程技术网

Linq 如何正确订阅已更改的反应对象序列?

Linq 如何正确订阅已更改的反应对象序列?,linq,system.reactive,reactive-programming,reactiveui,Linq,System.reactive,Reactive Programming,Reactiveui,关于ReactiveUi的另一个问题。我有一个用于编辑表单的ViewModel。模型是反应对象。我只想在对象发生更改时启用savecommand。我的尝试: var canSaveCommand = this.WhenAnyValue(vm => vm.CurrentClient) .Where(client => client != null) .Select(client =>

关于ReactiveUi的另一个问题。我有一个用于编辑表单的ViewModel。模型是反应对象。我只想在对象发生更改时启用savecommand。我的尝试:

var canSaveCommand =
        this.WhenAnyValue(vm => vm.CurrentClient)
            .Where(client => client != null)
            .Select(client =>
                client.Changed
            )
            .Any();

但当窗体出现时,SaveCommand已启用。我的错误在哪里?

尝试将您的选择更改为SelectMany。然后,这将为您提供一个可观察到的要传递到Any的更改,而不是一个可观察到的要传递到Any的更改。

您希望使用not 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;} 
 }
vs

AudioListViewModel viewModel;

viewModel
    .CurrentAudioChannelObservable
    .Select(current=>current.AudioFrameObservable)
    .Switch()
    .Subscribe(frame=>frame.Play());
在第一个版本中,当我们更改音频节点的选择时,我们添加了越来越多的订阅。音频输出很快就会变成混合频道的乱七八糟。在第二个版本中,一次只订阅一个频道,音频输出仅播放单个频道的输出

很多人在开始使用RX时都会犯这个错误。例如,我发现一个使用SelectMany而不是Switch的

然而 在ReactiveUI中有一种内置的方式来以清晰的方式实现这一点

实际上,有另一种方法可以实现您想要的,我将把它放在另一个答案中,只是为了向您展示如何使用ReactiveUI

var canSaveCommand =
        this
          .WhenAnyObservable(vm => vm.CurrentClient.Changed)
          .StartWith(false);
请注意,null不必显式处理,尽管您应该以false开头,以确保在没有可观测值可用时存在值

当任何可观测的行为非常像Rx运算符CombineTest时,在 它监视一个或多个可观察对象,并允许您定义 基于每个项目的最新值的投影。什么时候可以观察到 与CombineTest的不同之处在于其参数是表达式, 而不是直接引用目标可观测值。影响 这一区别在于,手表设置的时间不可观测 与发生时存在的特定可观察实例相关联 订阅也就是说,表达式指向的可观察对象可以 稍后将被替换,新的可观测结果仍将被替换 捕获。当视图 希望观察viewmodel上的可观察对象,但viewmodel可以 将在视图的生存期内被替换。而不是需要 每次更改viewmodel后,重新订阅可观察到的目标, 您可以使用WhenyObservable指定要监视的“路径”。这 允许您在视图中使用单个订阅,而不考虑 目标viewmodel的生命周期


SelectMany不会从以前的客户端取消订阅。它将合并来自所有客户端的事件,并导致一些讨厌的bug。Where之后的Take1将很快修复这些问题,但是,假设用户有一个场景,其中CurrentClient多次更改,而在许多场景中情况并非如此。如果您明确表示只有一个值可用,则最好使用Task ie提供方法Task GetClientAsync。对于属性,更安全的做法是假设它们总是可以更改的,如果它们在软件的v1中没有更改,那么在v9中它们可能会更改,并且您的假设会烧坏您。更改的问题是standart event wraper-IObservable,需要转换为bool。在我的例子中,我最终在VM HasChanges中添加了另一个可观察属性,并在任何.P.S的订阅中设置。对于WPF来说,ReactiveUI看起来很棒,但它有许多缺陷,并且隐含着奇异性。有时我想随地吐痰,然后离开他隐含的奇异性???…隐含的特殊性/特征。我还是不明白你的意思抱歉。你能举个例子吗。
AudioListViewModel viewModel;

viewModel
    .CurrentAudioChannelObservable
    .Select(current=>current.AudioFrameObservable)
    .Switch()
    .Subscribe(frame=>frame.Play());
var canSaveCommand =
        this
          .WhenAnyObservable(vm => vm.CurrentClient.Changed)
          .StartWith(false);