我有一个列表,其中有很多实时更新,所以我想每隔 1 秒将这个 Observable 集合中的所有更改复制到另一个集合中。我该怎么做?
我尝试的是:
var temp = CalculateMyObservableCollection();
var temp2 = (INotifyCollectionChanged) temp.SourceCollection;
Observable.FromEventPattern<CollectionChangeEventArgs>(temp2, "CollectionChanged")
.Throttle(new TimeSpan(1000))
.Select(i => i.Sender)
.Subscribe(UpdateItems);
private void UpdateItems(object obj)
{
if (obj is MyClass)
Items.AddNewItem(obj as MyClass);
}
这似乎是完全错误的!!
最佳答案
我已经实现了一个节流的可观察集合,也许可以解决您的问题。
INotifyCollectionChanged
接口(interface)可以提供详细的更改通知,描述确切的集合更改,其中更改操作由 Action
指示事件参数的属性。但是,当更改受到限制时,您将失去跟踪有关更改的详细信息的能力,因为无法表达添加和删除元素的复杂更改。相反 Reset必须使用操作来表示集合的内容发生了巨大变化。
class ThrottledObservableCollection<T> : IReadOnlyCollection<T>, INotifyCollectionChanged, INotifyPropertyChanged, IDisposable {
List<T> _list;
IDisposable _subscription;
public ThrottledObservableCollection(ObservableCollection<T> source, TimeSpan throttleInterval) {
if (source == null)
throw new ArgumentNullException("source");
_list = new List<T>(source);
_subscription = Observable
.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
handler => source.CollectionChanged += handler,
handler => source.CollectionChanged -= handler
)
.Throttle(throttleInterval)
.Subscribe(HandleSourceChanged);
}
void HandleSourceChanged(EventPattern<NotifyCollectionChangedEventArgs> eventPattern) {
var source = (IEnumerable<T>) eventPattern.Sender;
_list = new List<T>(source);
OnPropertyChanged("Count");
OnCollectionChanged();
}
public Int32 Count { get { return _list.Count; } }
public IEnumerator<T> GetEnumerator() {
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(String propertyName) {
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected void OnCollectionChanged() {
var handler = CollectionChanged;
if (handler != null)
handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void Dispose() {
Dispose(true);
}
protected void Dispose(Boolean disposing) {
_subscription.Dispose();
}
}
请注意,此类不是线程安全的,如果多个线程同时更改源集合,您可能需要一些额外的保护。
这里是如何使用集合:
var observableCollection = new ObservableCollection<Item>();
var throttledObservableCollection = new ThrottledObservableCollection<Item>(
observableCollection,
TimeSpan.FromSeconds(1)
);
throttledObservableCollection.CollectionChanged += ...
// 2 CollectionChanged events will fire from this code.
observableCollection.Add(new Item());
observableCollection.Add(new Item());
Thread.Sleep(TimeSpan.FromSeconds(1.1));
observableCollection.Add(new Item());
关于c# - 将列表(ObservableCollection)复制到另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25037744/