如何在ReactiveUI中使用WhenAny(...)合并多个observable?

nDe*_*Dev 3 system.reactive observable reactiveui

我有一个问题,这是对本网站提出的以下问题的扩展.

当返回类型不重要时,是否有更优雅的方法来合并observable?

我有一个IObservable<Unit>(比方说X),一个反应集合(Y)和一个属性(Z).返回类型并不重要.我只想在任何这些改变时订阅.

我知道如何观察所有3并Subscribe使用Observable.Merge如下.

Observable.Merge(X, Y.Changed, ObservableForProperty(Z).Select(_ => Unit.Default)).Subscribe(..)
Run Code Online (Sandbox Code Playgroud)

它有效.

但是,当我尝试使用WhenAny(...,....,....).Subscribe()时,我的X更改时不会触发订阅.做上述使用WhenAny(...)而不是Observable.Merge(..)?? 的语法是什么?

我喜欢使用,WhenAny(....)因为我ReactiveUI在其他地方使用.

示例:假设我有一个派生自ReactiveObject以下属性的类.

public class AnotherVM : ReactiveObject
{
    public bool IsTrue
    {
        get { return this.isTrue; }
        set { this.RaiseAndSetIfChanged(x => x.isTrue, ref this.isTrue, value); }
    }

    public IObservable<Unit> Data
    {
        get { return this.data; }
    }

    public ReactiveCollection MyCol
    {
       get { return Mycol; }
    }    
}

public class MyVM : ReactiveObject
{
    MyVM
    {
       // do WhenAny or Observable.Merge here....
    }
}
Run Code Online (Sandbox Code Playgroud)

我想在遵守上述特性AnotherVM使用类Observable.Merge(..)WhenAny(...)MyVM类.我发现当我在MyVM使用中订阅上述内容WhenAny(...)或者Merge(...)当3个属性中的任何一个更改时,我并不总是收到通知.

Jam*_*rld 6

WhenAny 不用于监视任意可观察对象集,它用于监视ReactiveUI支持的对象的属性(如ReactiveObject或反应集合).

对于组合可观察流的变化的一般情况,Observable.Merge是正确的方法.

编辑

我注意到您已将Data和MyCol属性声明为只读.如果您使用Merge这样的:

Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
                   this.Data,
                   this.MyCol.CollectionChanged.Select(v=>Unit.Default))
Run Code Online (Sandbox Code Playgroud)

...那么你必须小心不要改变支持领域.如果你这样做,那么你会得到失踪的事件 - 也许这就是发生的事情?

在这种情况下,您需要将这些属性连接到RaiseAndSetIfChanged并使用a Switch来跟踪 - 例如,如果this.data可以改变那么您需要(我在这里使用ReactiveUI 5 + .NET 4.5,以防RaiseAndSetIfChanged语法看起来很奇怪):

public IObservable<Unit> Data
{
    get { return this.data; }
    private set { this.RaiseAndSetIfChanged(ref data, value); }
}
Run Code Online (Sandbox Code Playgroud)

你的合并将是这样的:

Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
                   this.WhenAnyObservable(x => x.Data),
                   this.MyCol.CollectionChanged.Select(v=>Unit.Default))
Run Code Online (Sandbox Code Playgroud)

WhenAnyObservable在概念上等同于:

WhenAny(x => x.Data, vm => vm.Value).Switch()
Run Code Online (Sandbox Code Playgroud)

使用Switch切换到Data更改时的最新值.不要忘记使用setter来更改数据值!