c# - 将列表(ObservableCollection)复制到另一个

标签 c# list system.reactive

我有一个列表,其中有很多实时更新,所以我想每隔 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/

相关文章:

c# - Observable.FromEvent 和 CreateDelegate 参数映射

java - RxJava : How can I reset a long running hot observable chain?

c# - Windows 7 上的 LINQ 性能较慢

c# - 通过WCF数据服务和LINQ保存数据时,InvalidOperationException“类型为'Y'的对象的成员'X'的值已更改。”

C++ vector 和列表插入

jquery计算顶级UL中的li数

.net - 没有主题的热可观察

c# - 如何将泛型组合的概念封装成一个新的类型?

c# - 我的类(class)应该订阅自己的公共(public)事件吗?

python - 从另一个列表中删除一个列表中的所有值?