静态ObservableCollection事件未触发

时间:2017-03-23 13:28:30

标签: c# linq events observablecollection

我使用static更新了以下ObservableCollection linq。为什么事件没有解雇?

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;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

第一步:给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);
}

如果您真的想一次性更换集合,则需要将处理程序添加到 new 集合中:

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);
}