如何解决我们如何从IObservable <IList <T >>创建IObservableList <T>? 问题上下文我尝试过的
问题
我们如何从DynamicData到IObservable<IReadOnlyList<T>>
到IObservableList<T>
?
上下文
我在项目中同时使用Reactive extensions和DynamicData。
我目前有一个随时间变化的字符串列表。我身为IObservable<IReadOnlyList<string>>
。它产生如下更新:
-
["A","C","F"]
-
["A","B","C"]
我想将其转换为IObservableList<string>
,这样会产生如下更新:
- 在索引0处添加“ A”,“ C”,“ F”
- 在索引1处添加“ B”
- 从索引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","F" });
source.OnNext(new[] { "A","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,F,A] (operation: Add at index 3)
[A,A,B] (operation: Add at index 4)
[A,B,C] (operation: Add at index 5)
我们可以看到[A,C]
与[A,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] (operation: Remove at index -1)
[A,B] (operation: Add at index 2)
我们可以看到[A,B]
与[A,C]
不同。
谢谢!
解决方法
我对DynamicData不太熟悉,但是我相信这会带来接近预期结果的结果:
using DynamicData;
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Subject<IReadOnlyList<string>> source = new Subject<IReadOnlyList<string>>();
var list = ObservableChangeSet.Create<string>(sourceList =>
{
return source
.Subscribe(newItems =>
{
sourceList.Edit(items =>
{
for (var i = 0; i < newItems.Count; i++)
{
if (items.Count <= i) items.Add(newItems[i]);
else
{
if (items[i] != newItems[i])
{
items[i] = newItems[i];
}
}
}
while (items.Count > items.Count) items.RemoveAt(items.Count - 1);
});
});
}).AsObservableList();
source.OnNext(new[] { "A","C","F" });
source.OnNext(new[] { "A","B","C" });
Console.ReadLine();
}
}
}
不幸的是,我没有弄清楚如何获得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>
编辑:下面给出了您想要的确切输出,但是我没有测试每个输出的性能(对于较大的列表,插入可能会变得昂贵):
using DynamicData;
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Subject<IReadOnlyList<string>> source = new Subject<IReadOnlyList<string>>();
var list = ObservableChangeSet.Create<string>(sourceList =>
{
return source
.Subscribe(newItems =>
{
sourceList.Edit(items =>
{
for (var i = 0; i < newItems.Count; i++)
{
if (items.Count <= i) items.Add(newItems[i]);
else
{
if (items[i] != newItems[i])
{
items.Insert(i,newItems[i]);
}
}
}
while (items.Count > newItems.Count) items.RemoveAt(items.Count - 1);
});
});
}).AsObservableList();
source.OnNext(new[] { "A","C" });
Console.ReadLine();
}
}
}
-
AddRange. 3 changes
-
Add. Current: B,Previous: <None> Index 1
-
Remove. Current: C,Previous: <None> Index 2
如果字符串是唯一的,为什么不使用ToObservableChangeSet
的重载来设置字符串作为键。这样,如果您的新列表中不包含“ F”,则说明您应该删除现有的“ F”。
也许有一种更简单的方法,但是您可能必须临时插入自己的索引。如果您不需要通过绑定集合跟踪更改,则可以从更改集中进行以下操作:
Subject<IReadOnlyList<string>> source = new Subject<IReadOnlyList<string>>();
IObservable<IEnumerable<string>> observableOfList = source;
IObservable<IChangeSet<(string,int),string>> observableOfChangeSet = source.Select(x =>
{
return x.Select((item,index) => (item,index));
}).ToObservableChangeSet<(string,string>(x=>x.Item1);
observableOfChangeSet
.Sort(SortExpressionComparer<(string,int)>.Ascending(x => x.Item2))
.OnItemAdded(x=> Debug.WriteLine($"Item {x.Item1} was added to index {x.Item2}"))
.OnItemRemoved(x => Debug.WriteLine($"Item {x.Item1} was removed from index {x.Item2}"))
.OnItemUpdated((x,prev) => Debug.WriteLine($"Item {prev.Item1} at index {prev.Item2} was updated to Item {x.Item1} at index {x.Item2}"))
.Transform(x=>
{
Debug.WriteLine($"Item: {x.Item1} at index: {x.Item2}");
return x.Item1;
})
.Bind(out ReadOnlyObservableCollection<string> boundCollection)
.Subscribe();
source.OnNext(new[] { "A","F" });
source.OnNext(new[] { "A","C" });
此代码的调试输出:
Item A was added to index 0
Item C was added to index 1
Item F was added to index 2
Item: A at index: 0
Item: C at index: 1
Item: F at index: 2
Item B was added to index 1
Item F was removed from index 2
Item A at index 0 was updated to Item A at index 0
Item C at index 1 was updated to Item C at index 2
Item: A at index: 0
Item: B at index: 1
Item: C at index: 2
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。