10年后,现在我在我的项目中必须使用C#,而且我不希望触发多个OnCollectionChanged。我已经将@outbred的答案修改为一个扩展类。
使用方法:
var stuff = new ObservableCollection<Stuff>() {...};
...
stuff.ReplaceCollection(newThings);
ObservableCollectionExtensions.cs
是一个文件:
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace System.Collections.ObjectModel
{
public static class ObservableCollectionExtensions
{
private static BindingFlags ProtectedMember = BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic;
private static BindingFlags ProtectedProperty = BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic;
private static void InsertWithoutNotify<T>(this ObservableCollection<T> collection, IEnumerable<T> items, int index = -1)
{
if (collection == null || items == null || !items.Any()) return;
Type type = collection.GetType();
type.InvokeMember("CheckReentrancy", ProtectedMember, null, collection, null);
PropertyInfo itemsProp = type.BaseType.GetProperty("Items", ProtectedProperty);
IList<T> protectedItems = itemsProp.GetValue(collection) as IList<T>;
int start = index > -1 ? index : protectedItems.Count();
int end = items.Count();
for (int i = 0; i < end; i++)
{
protectedItems.Insert(start + i, items.ElementAt(i));
}
type.InvokeMember("OnPropertyChanged", ProtectedMember, null,
collection, new object[] { new PropertyChangedEventArgs("Count") });
type.InvokeMember("OnPropertyChanged", ProtectedMember, null,
collection, new object[] { new PropertyChangedEventArgs("Item[]") });
}
public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items)
{
if (collection == null || items == null || !items.Any()) return;
Type type = collection.GetType();
InsertWithoutNotify(collection, items);
type.InvokeMember("OnCollectionChanged", ProtectedMember, null,
collection, new object[] {
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)
});
}
public static void InsertRange<T>(this ObservableCollection<T> collection, int index, IEnumerable<T> items)
{
if (collection == null || items == null || !items.Any()) return;
Type type = collection.GetType();
InsertWithoutNotify(collection, items, index);
type.InvokeMember("OnCollectionChanged", ProtectedMember, null,
collection, new object[] {
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)
});
}
public static void ReplaceCollection<T>(this ObservableCollection<T> collection, IEnumerable<T> items)
{
if (collection == null || items == null || !items.Any()) return;
Type type = collection.GetType();
PropertyInfo itemsProp = type.BaseType.GetProperty("Items", ProtectedProperty);
IList<T> protectedItems = itemsProp.GetValue(collection) as IList<T>;
protectedItems.Clear();
InsertWithoutNotify(collection, items);
type.InvokeMember("OnCollectionChanged", ProtectedMember, null,
collection, new object[] {
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)
});
}
}
}
OnPropertyChanged
。 - sll