![](/img/trans.png)
[英]CollectionChanged Event is not firing on a static ObservableCollection
[英]Static ObservableCollection Event is not firing
我有以下使用linq
更新的static
ObservableCollection
。 為什么事件沒有解雇?
public static class myViewModel
{
private static ObservableCollection<ObjA> CollectionA = new ObservableCollection<ObjA>();
private static ObservableCollection<ObjB> CollectionB = new ObservableCollection<ObjB>();
static myViewModel()
{
CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler);
CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, True));
}
private static void myHandler(object sender, NotifyCollectionChangedEventArgs e)
{
//To do
throw new NotImplementedException();
}
private static void updateCollection()
{
foreach (var x in CollectionA)
{
CollectionA.field=5;
}
}
}
第一步:為CollectionA
一個事件處理程序。
CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler);
第二步: 丟棄 CollectionA
並將其替換為沒有處理程序的不同集合。
CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, true));
看看你在那里做了什么?
CollectionA
返回對集合對象的引用。 您沒有向該集合對象添加項目。 您正在使用其他集合對象替換該集合對象。
而是將項目添加到現有集合中:
CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler);
foreach (var x in CollectionB.Select(abc=> new ObjA(abc, true)))
{
CollectionA.Add(x);
}
如果您確實想要一次性替換集合,則需要將處理程序添加到新集合中:
CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, true));
CollectionA.CollectionChanged += myHandler;
如果myHandler
具有正確的參數和返回類型,則不需要new NotifyCollectionChangedEventHandler
。
處理這類事情的常用方法是使CollectionA
成為一個添加處理程序本身的屬性:
private static ObservableCollection<ObjA> _collectionA;
public static ObservableCollection<ObjA> CollectionA {
get { return _collectionA; }
set {
if (_collectionA != value)
{
// Remove handler from old collection, if any
if (_collectionA != null)
{
_collectionA.CollectionChanged -= myHandler;
}
_collectionA = value;
if (_collectionA != null)
{
_collectionA.CollectionChanged += myHandler;
// Whatever myHandler does on new items, you probably want to do
// that here for each item in the new collection.
}
}
}
}
static myViewModel()
{
// Now, whenever you replace CollectionA, the setter will add the changed
// handler automatically and you don't have to think about it.
CollectionA = new ObservableCollection(CollectionB.Select(abc=> new(abc, True));
}
現在,什么是我們與項目在做什么? 也許我們想知道它們的屬性何時發生變化。 ObservableCollection
不會為我們這樣做,但我們可以自己連接它。
考慮以更方便可重用的方式重構此代碼的方法很有趣。
private static ObservableCollection<ObjA> _collectionA;
public static ObservableCollection<ObjA> CollectionA
{
get { return _collectionA; }
set
{
if (_collectionA != value)
{
// Remove handler from old collection, if any
if (_collectionA != null)
{
_collectionA.CollectionChanged -= myHandler;
}
// 1. Remove property changed handlers from old collection items (if old collection not null)
// 2. Add property changed to new collection items (if new collection not null)
AddAndRemovePropertyChangedHandlers(_collectionA, value, ObjA_PropertyChanged);
_collectionA = value;
if (_collectionA != null)
{
_collectionA.CollectionChanged += myHandler;
}
}
}
}
// NotifyCollectionChangedEventArgs gives us non-generic IList rather than IEnumerable
// but all we're doing is foreach, so make it as general as possible.
protected static void AddAndRemovePropertyChangedHandlers(
System.Collections.IEnumerable oldItems,
System.Collections.IEnumerable newItems,
PropertyChangedEventHandler handler)
{
if (oldItems != null)
{
// Some items may not implement INotifyPropertyChanged.
foreach (INotifyPropertyChanged oldItem in oldItems.Cast<Object>()
.Where(item => item is INotifyPropertyChanged))
{
oldItem.PropertyChanged -= handler;
}
}
if (newItems != null)
{
foreach (INotifyPropertyChanged newItem in newItems.Cast<Object>()
.Where(item => item is INotifyPropertyChanged))
{
newItem.PropertyChanged += handler;
}
}
}
private static void ObjA_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
private static void myHandler(object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// If e.Action is Reset, you don't get the items that were removed. Oh well.
AddAndRemovePropertyChangedHandlers(e.OldItems, e.NewItems, ObjA_PropertyChanged);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.