如何在 ReactiveUI、C# 中将一个可观察对象的反应列表动态合并到一个可观察对象中
How to dynamically merge a reactivelist of observables into one observable in ReactiveUI, C#
我正在尝试使用 ReactiveUI 来制定一些可观察对象。虽然有些东西已经运行良好,但我仍然无法为其他东西找到合适的 ReactiveUI 方法。我还是 ReactiveUI 的新手。
public class ViewModel : ReactiveObject {
public ReactiveList<A> aList {get;}
}
public class A : ReactiveObject {
public ReactiveList<B> bList {get;}
}
public class B : ReactiveObject {
//some properties
}
我有一个ReactiveList
aList
。它的项目是 ReactiveObject
class A
,其中包含另一个 ReactiveList
bList
。 bList
项为 属性,共 ReactiveObject
class B
。
从 aList
开始,我如何应对 aList
、bList
及其所有属性中的任何更改?
我正在尝试这样的事情:
Observable.Merge(viewModel.aList.Select(x => Observable.Merge(x.bList.Select(y => y.Changed))))
但是,当执行此代码时,这只会观察 B
中已经存在的变化。有什么东西可以自动观察 aList
和 bList
的变化并订阅新项目吗?
或者 Observable.Merge
可以观看 ReactiveList
并自动订阅任何新项目并取消订阅已删除的项目吗?
我知道,我可以手动完成,但这可能不会按照预期的方式使用 ReactiveUI。有什么想法吗?
ReactiveList
上的 Changed
属性 会在列表更改时通知您。使用它来了解何时更新订阅以包含 ReactiveList
s.
中的更改
要获得每次 ReactiveList<A>
和 ReactiveList<B>
变化时滴答作响的 observable,您可以这样做:
aList.Changed
.Select(change => Observable.Merge(viewModel.aList.Select(x => Observable.Merge(x.bList.Select(y => y.Changed)))) // Create observable to notify when the sub collections change
.StartWith(change) // Send the notification that aList has changed immediately
)
.Switch() // Only subscribe to the latest change notifications from the sub collections in the most recent aList
.Subscribe(changes => { /* Do something */});
除了使用 ReactiveList,您还可以尝试我们的库 ReactiveCompositeCollections,它允许您使用 LINQ 展平可观察集合。
public class ViewModel : ReactiveObject {
public ICompositeSourceList<A> aList {get;}
}
public class A : ReactiveObject {
public ICompositeSourceList<B> bList {get;}
}
public class B : ReactiveObject {
//some properties
}
然后
ViewModel vm = ... ;
IComposteList<B> all =
from aItem in vm.aList
from bItem in aItem.bList
select bItem;
// Subscribe to the stream of flattened items
all.Items.Subscribe((ImmutableList<B> bItems)=>DoSometing(bItems));
// or create an INPC object with a property Items
using(var s = allLines.Subscribe()){
RenderLines(s.Items);
}
好消息是,这不是基于 IEnumerable 的 LINQ,而是基于 ICompositeCollection 的 LINQ,其中 ICompositeCollection 是一个反应性集合。源列表中的任何更改都会反应性地投射到结果列表中。
内部结构都使用不可变列表,因此对于大型集合,性能可能是个问题。
可以通过
将 ICompositeCollection 转换为 WPF 可用的 ObservableCollection
ObservableCollection<B> observableBs =
all.CreateObservableCollection(EqualityComparer<B>.Default)
更多详情请见 https://github.com/Weingartner/ReactiveCompositeCollections#using-icompositecollection-with-wpf
我正在尝试使用 ReactiveUI 来制定一些可观察对象。虽然有些东西已经运行良好,但我仍然无法为其他东西找到合适的 ReactiveUI 方法。我还是 ReactiveUI 的新手。
public class ViewModel : ReactiveObject {
public ReactiveList<A> aList {get;}
}
public class A : ReactiveObject {
public ReactiveList<B> bList {get;}
}
public class B : ReactiveObject {
//some properties
}
我有一个ReactiveList
aList
。它的项目是 ReactiveObject
class A
,其中包含另一个 ReactiveList
bList
。 bList
项为 属性,共 ReactiveObject
class B
。
从 aList
开始,我如何应对 aList
、bList
及其所有属性中的任何更改?
我正在尝试这样的事情:
Observable.Merge(viewModel.aList.Select(x => Observable.Merge(x.bList.Select(y => y.Changed))))
但是,当执行此代码时,这只会观察 B
中已经存在的变化。有什么东西可以自动观察 aList
和 bList
的变化并订阅新项目吗?
或者 Observable.Merge
可以观看 ReactiveList
并自动订阅任何新项目并取消订阅已删除的项目吗?
我知道,我可以手动完成,但这可能不会按照预期的方式使用 ReactiveUI。有什么想法吗?
ReactiveList
上的 Changed
属性 会在列表更改时通知您。使用它来了解何时更新订阅以包含 ReactiveList
s.
要获得每次 ReactiveList<A>
和 ReactiveList<B>
变化时滴答作响的 observable,您可以这样做:
aList.Changed
.Select(change => Observable.Merge(viewModel.aList.Select(x => Observable.Merge(x.bList.Select(y => y.Changed)))) // Create observable to notify when the sub collections change
.StartWith(change) // Send the notification that aList has changed immediately
)
.Switch() // Only subscribe to the latest change notifications from the sub collections in the most recent aList
.Subscribe(changes => { /* Do something */});
除了使用 ReactiveList,您还可以尝试我们的库 ReactiveCompositeCollections,它允许您使用 LINQ 展平可观察集合。
public class ViewModel : ReactiveObject {
public ICompositeSourceList<A> aList {get;}
}
public class A : ReactiveObject {
public ICompositeSourceList<B> bList {get;}
}
public class B : ReactiveObject {
//some properties
}
然后
ViewModel vm = ... ;
IComposteList<B> all =
from aItem in vm.aList
from bItem in aItem.bList
select bItem;
// Subscribe to the stream of flattened items
all.Items.Subscribe((ImmutableList<B> bItems)=>DoSometing(bItems));
// or create an INPC object with a property Items
using(var s = allLines.Subscribe()){
RenderLines(s.Items);
}
好消息是,这不是基于 IEnumerable 的 LINQ,而是基于 ICompositeCollection 的 LINQ,其中 ICompositeCollection 是一个反应性集合。源列表中的任何更改都会反应性地投射到结果列表中。
内部结构都使用不可变列表,因此对于大型集合,性能可能是个问题。
可以通过
将 ICompositeCollection 转换为 WPF 可用的 ObservableCollectionObservableCollection<B> observableBs =
all.CreateObservableCollection(EqualityComparer<B>.Default)
更多详情请见 https://github.com/Weingartner/ReactiveCompositeCollections#using-icompositecollection-with-wpf