【问题标题】:How to dynamically merge a reactivelist of observables into one observable in ReactiveUI, C#如何在 ReactiveUI、C# 中将可观察对象的反应列表动态合并为一个可观察对象
【发布时间】:2017-03-06 16:10:36
【问题描述】:

我正在尝试使用 ReactiveUI 来制定一些 observables。虽然有些事情已经很好地工作了,但我仍然无法为其他事情找到合适的 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。它的项目是ReactiveObjectA,其中包含另一个ReactiveList bListbList 项目作为 ReactiveObjectB 的属性。 从aList 开始,我如何应对aListbList 及其所有属性中的任何更改?

我正在尝试这样的事情:

Observable.Merge(viewModel.aList.Select(x => Observable.Merge(x.bList.Select(y => y.Changed))))

但是,这只会在执行此代码时观察B 中已经存在的更改。有什么东西可以自动观察aListbList的变化并订阅新项目吗?

或者Observable.Merge 可以观看ReactiveList 并自动订阅任何新项目并取消订阅已删除的项目?

我知道,我可以手动完成,但这可能不会按照预期的方式使用 ReactiveUI。有什么想法吗?

【问题讨论】:

    标签: c# reactiveui


    【解决方案1】:

    ReactiveList 上的 Changed 属性会在列表发生更改时通知您。使用它来了解何时更新订阅以包含 ReactiveLists 中的更改。

    要获得每次 ReactiveList&lt;A&gt;ReactiveList&lt;B&gt; 更改时都会滴答的 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 */});
    

    【讨论】:

      【解决方案2】:

      您可以尝试使用我们的库 ReactiveCompositeCollections 而不是使用 ReactiveList,它允许您使用 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-11
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 1970-01-01
        • 1970-01-01
        • 2022-08-19
        • 1970-01-01
        相关资源
        最近更新 更多