如何在ReactiveUI中使用WhenAny(...)合并多个可观察对象? [英] How do I merge several observables using WhenAny(...) in ReactiveUI?
问题描述
我有一个问题,是对该网站提出的以下问题的扩展.
I have a question which is an extension of the following question raised on this site.
我有一个IObservable<Unit>
(让我们说X
),一个反应式集合(Y
)和一个属性(Z
).返回类型并不重要.我只想在这些更改中的任何一个订阅.
I have an IObservable<Unit>
(lets say X
), a reactive collection (Y
) and a property (Z
). Return type is not important. I just want to subscribe when any of these change.
我知道如何使用Observable.Merge
如下观察所有3和Subscribe
.
I know how to observe all 3 and Subscribe
using Observable.Merge
as below.
Observable.Merge(X, Y.Changed, ObservableForProperty(Z).Select(_ => Unit.Default)).Subscribe(..)
它有效.
但是,当我尝试使用WhenAny(...,....,....).Subscribe()
时,当我的X
更改时,订阅不会被触发.使用WhenAny(...)
而不是Observable.Merge(..)
进行上述操作的语法是什么?
However, when I try to use WhenAny(...,....,....).Subscribe()
, the subscribe does not get triggered when my X
changes. What is the syntax for doing the above using WhenAny(...)
rather than Observable.Merge(..)
??
我更喜欢使用WhenAny(....)
,因为我在其他地方使用ReactiveUI
.
I prefer to use WhenAny(....)
because I am using ReactiveUI
in other places.
示例:
说我有一个从ReactiveObject
派生的类,它具有以下属性.
Example:
Say I've got a class derived from ReactiveObject
with following properties.
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....
}
}
我想使用MyVM
类中的Observable.Merge(..)
或WhenAny(...)
来观察AnotherVM
类中的以上属性.我发现,当三个属性中的任何一个发生更改时,当我在MyVM
中使用WhenAny(...)
或Merge(...)
订阅上述内容时,并不会总是收到通知.
I want to observe the above properties in AnotherVM
class using Observable.Merge(..)
or WhenAny(...)
in MyVM
class. I found that I do not always get a notification when I subscribe to the above in MyVM
using WhenAny(...)
or Merge(...)
when either of the 3 properties change.
推荐答案
WhenAny
不是用于监视任意可观察对象集,而是用于监视ReactiveUI支持的对象的属性(例如ReactiveObject或反应性集合).
WhenAny
is not for monitoring across sets of arbitrary observables, it's for monitoring the properties of an object supported by ReactiveUI (like a ReactiveObject or reactive collection).
对于将可观察流中的更改合并在一起的一般情况,Observable.Merge
是正确的方法.
For the general case of combining changes in observable streams, Observable.Merge
is the right way to go.
编辑
我注意到您已声明Data和MyCol属性为只读.如果您使用这样的Merge
:
I note that you have declared the Data and MyCol properties read only. If you use a Merge
like this:
Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
this.Data,
this.MyCol.CollectionChanged.Select(v=>Unit.Default))
...然后您必须注意不要更改背景字段.如果这样做,那么您将丢失事件-也许这是正在发生的事情?
...then you must be careful not to change the backing fields. If you do, then you will get missing events - maybe this is what is happening?
在这种情况下,您需要将这些属性连接到RaiseAndSetIfChanged
并使用Switch
进行跟踪-例如如果this.data
可以更改,那么您将需要(我在这里使用ReactiveUI 5 + .NET 4.5,以防RaiseAndSetIfChanged语法看起来很奇怪):
In that case you would need to wire up those properties to RaiseAndSetIfChanged
and use a Switch
to keep track - e.g. if this.data
could change then you would need (I'm using ReactiveUI 5 + .NET 4.5 here in case the RaiseAndSetIfChanged syntax looks odd):
public IObservable<Unit> Data
{
get { return this.data; }
private set { this.RaiseAndSetIfChanged(ref data, value); }
}
您的合并将类似于:
Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
this.WhenAnyObservable(x => x.Data),
this.MyCol.CollectionChanged.Select(v=>Unit.Default))
WhenAnyObservable在概念上与此等效:
WhenAnyObservable is conceptually equivalent to this:
WhenAny(x => x.Data, vm => vm.Value).Switch()
使用切换到Data
的最新值.不要忘记使用设置器来更改数据值!
using Switch to flip over to the latest value of Data
when it changes. Don't forget to use the setter to change values of data!
这篇关于如何在ReactiveUI中使用WhenAny(...)合并多个可观察对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!