问题
我们如何从IObservable<IReadOnlyList<T>>
到IObservableList<T>
(来自DynamicData)?
上下文
我在我的项目中同时使用了Reactive扩展和DynamicData。
我目前有一个随时间变化的字符串列表。我有一个IObservable<IReadOnlyList<string>>
。它产生如下更新:
["A", "C", "F"]
["A", "B", "C", "F"]
["A", "B", "C"]
我想把它转换成一个IObservableList<string>
,它将产生如下更新:
1.在索引0处添加“A”、“C”、“F”
1.在索引1处添加“B”
1.从索引3中删除“F”
我所尝试的
我试过使用ToObservableChangeSet
扩展,但它没有正确的行为。
编码
Subject<IReadOnlyList<string>> source = new Subject<IReadOnlyList<string>>();
IObservable<IEnumerable<string>> observableOfList = source;
IObservable<IChangeSet<string>> observableOfChangeSet = source.ToObservableChangeSet<string>();
observableOfChangeSet
.Bind(out ReadOnlyObservableCollection<string> boundCollection)
.Subscribe();
((INotifyCollectionChanged)boundCollection).CollectionChanged += OnCollectionChanged;
source.OnNext(new[] { "A", "C", "F" });
source.OnNext(new[] { "A", "B", "C" });
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Debug.WriteLine($"[{string.Join(", ", (IEnumerable<string>)sender)}] (operation: {e.Action} at index {e.NewStartingIndex})");
}
输出
[A, C, F] (operation: Reset at index -1)
[A, C, F, A] (operation: Add at index 3)
[A, C, F, A, B] (operation: Add at index 4)
[A, C, F, A, B, C] (operation: Add at index 5)
正如我们所看到的[A, C, F, A, B, C]
与[A, B, C]
不同。
我也尝试过使用EditDiff
,但这不能保持列表的顺序。
编码
Subject<IReadOnlyList<string>> source = new Subject<IReadOnlyList<string>>();
IObservable<IEnumerable<string>> observableOfList = source;
IObservable<IChangeSet<string>> observableOfChangeSet = ObservableChangeSet.Create<string>(list =>
{
return observableOfList
.Subscribe(items => list.EditDiff(items, EqualityComparer<string>.Default));
});
observableOfChangeSet
.Bind(out ReadOnlyObservableCollection<string> boundCollection)
.Subscribe();
((INotifyCollectionChanged)boundCollection).CollectionChanged += OnCollectionChanged;
source.OnNext(new[] { "A", "C", "F" });
source.OnNext(new[] { "A", "B", "C" });
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Debug.WriteLine($"[{string.Join(", ", (IEnumerable<string>)sender)}] (operation: {e.Action} at index {e.NewStartingIndex})");
}
输出
[A, C, F] (operation: Reset at index -1)
[A, C] (operation: Remove at index -1)
[A, C, B] (operation: Add at index 2)
我们可以看到[A, C, B]
与[A, B, C]
不同。
谢谢!
3条答案
按热度按时间cgh8pdjw1#
如果字符串是唯一的,为什么不使用
ToObservableChangeSet
的重载,将字符串设置为键。这样,如果新列表不包含“F”,它就知道应该删除现有的“F”。也许有一个更简单的方法,但你可能需要临时插入你自己的索引。如果你不需要通过绑定的集合来跟踪更改,你可以从变更集中这样做:
这段代码的调试输出:
hc2pp10m2#
我对DynamicData不是很熟悉,但我相信这会给出一些接近预期结果的东西:
不幸的是,我没有弄清楚如何获得
Add "B" at index 1
,但当前输出如下:AddRange. 3 changes
3 Changes
Replace. Current: B, Previous: C
Replace. Current: C, Previous: F
Add. Current: F, Previous: <None>
Remove. Current: C, Previous: <None>
**编辑:**下面给出了你想要的确切输出,但我还没有测试每一个的性能(对于更大的列表,插入可能会变得昂贵):
AddRange. 3 changes
Add. Current: B, Previous: <None> Index 1
Remove. Current: C, Previous: <None> Index 2
q0qdq0h23#
最后我写了一个自定义解决方案。
它是开源的,也提供了nuget包。
要解决原始问题,请安装以下软件包。
CollectionTracking.DynamicData
System.Reactive
然后,您可以使用如下方法。