简体   繁体   English

静态ObservableCollection事件未触发

[英]Static ObservableCollection Event is not firing

I have the following static ObservableCollection that gets updated using linq . 我有以下使用linq更新的static ObservableCollection Why the event is not firing ? 为什么事件没有解雇?

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

Step one: Give CollectionA an event handler. 第一步:为CollectionA一个事件处理程序。

CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler);

Step Two: Discard CollectionA and replace it with a different collection that has no handler. 第二步: 丢弃 CollectionA并将其替换为没有处理程序的不同集合。

CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, true));

See what you did there? 看看你在那里做了什么?

CollectionA returns a reference to a collection object. CollectionA返回对集合对象的引用。 You aren't adding items to that collection object. 您没有向该集合对象添加项目。 You are replacing that collection object with a different collection object. 您正在使用其他集合对象替换该集合对象。

Add the items to the existing collection instead: 而是将项目添加到现有集合中:

CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler);

foreach (var x in CollectionB.Select(abc=> new ObjA(abc, true)))
{
    CollectionA.Add(x);
}

If you really want to replace the collection all at once, you need to add the handler to the new collection: 如果您确实想要一次性替换集合,则需要将处理程序添加到集合中:

CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, true));

CollectionA.CollectionChanged += myHandler;

If myHandler has the correct parameters and return type, you don't need new NotifyCollectionChangedEventHandler . 如果myHandler具有正确的参数和返回类型,则不需要new NotifyCollectionChangedEventHandler

The usual way to handle this type of thing is to make CollectionA a property which adds the handler itself: 处理这类事情的常用方法是使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));
}

Update 更新

Now, what what are we doing with the items? 现在,什么我们与项目在做什么? Maybe we want to know when their properties change. 也许我们想知道它们的属性何时发生变化。 ObservableCollection won't do that for us, but we can wire it up ourselves. ObservableCollection不会为我们这样做,但我们可以自己连接它。

It's fun to think about ways to refactor this code in a more conveniently reusable way. 考虑以更方便可重用的方式重构此代码的方法很有趣。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM