有效地向ObservableCollection添加一系列值

我有一个ObservableCollection项目绑定到我的视图中的列表控件。

我有一种情况,我需要在集合的开头添加一大块值。 Collection.Insert文档将每个插入指定为O(n)操作,每个插入也生成一个CollectionChanged通知。

因此,我希望在一次移动中插入整个范围的项目,这意味着只有一个基础列表的随机播放,并且希望有一个CollectionChanged通知(可能是“重置”)。

Collection不会公开任何执行此操作的方法。 List具有InsertRange() ,但是IListCollection通过其Items属性公开不会。

有没有办法做到这一点?

ObservableCollection公开受保护的Items属性,该属性是没有通知语义的基础集合。 这意味着您可以通过inheritanceObservableCollection来构建一个能够满足您需求的集合:

 class RangeEnabledObservableCollection : ObservableCollection { public void InsertRange(IEnumerable items) { this.CheckReentrancy(); foreach(var item in items) this.Items.Add(item); this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } 

用法:

 void Main() { var collection = new RangeEnabledObservableCollection(); collection.CollectionChanged += (s,e) => Console.WriteLine("Collection changed"); collection.InsertRange(Enumerable.Range(0,100)); Console.WriteLine("Collection contains {0} items.", collection.Count); } 

为了使上述答案有用,无需使用reflection派生新的基类,这是一个例子:

 public static void InsertRange(this ObservableCollection collection, IEnumerable items) { var enumerable = items as List ?? items.ToList(); if (collection == null || items == null || !enumerable.Any()) { return; } Type type = collection.GetType(); type.InvokeMember("CheckReentrancy", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, null, collection, null); var itemsProp = type.BaseType.GetProperty("Items", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance); var privateItems = itemsProp.GetValue(collection) as IList; foreach (var item in enumerable) { privateItems.Add(item); } type.InvokeMember("OnPropertyChanged", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, null, collection, new object[] { new PropertyChangedEventArgs("Count") }); type.InvokeMember("OnPropertyChanged", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, null, collection, new object[] { new PropertyChangedEventArgs("Item[]") }); type.InvokeMember("OnCollectionChanged", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, null, collection, new object[]{ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)}); } 

这个答案没有向我展示DataGrid中的新条目。 这个OnCollectionChanged对我有用:

 public class SilentObservableCollection : ObservableCollection { public void AddRange(IEnumerable enumerable) { CheckReentrancy(); int startIndex = Count; foreach (var item in enumerable) Items.Add(item); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List(enumerable), startIndex)); OnPropertyChanged(new PropertyChangedEventArgs("Count")); OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); } } 

示例:所需步骤0,10,20,30,40,50,60,70,80,90,100 – > min = 0,max = 100,steps = 11

  static int min = 0; static int max = 100; static int steps = 11; private ObservableCollection restartDelayTimeList = new ObservableCollection ( Enumerable.Range(0, steps).Select(l1 => (min + (max - min) * ((double)l1 / (steps - 1))).ToString()) );