简体   繁体   中英

How to clone the ObservableCollection<T>.CollectionChanged event?

I am trying to copy an ObservableCollection into an ObservableCollection-derived type, and I want to preserve the CollectionChanged event.

So far I have:

public class PartitionCollection : ObservableCollection<AislePartition>
{
    public PartitionCollection(ObservableCollection<AislePartition> other)
    : base(other)
    {

    }

    // ...

    protected override void InsertItem(int index, AislePartition item)
    {
         // Important custom logic runs here
         if (/* */)
             base.InsertItem(index, item);
         else
             Merge(item);
    }

    protected void Merge(AislePartition item)
    {
         // ...
    }
}

It copies the collection fine but I do need to get the CollectionChanged event too.

Any way of doing that ? Thanks

EDIT:

Before: 在构造函数调用之前 After: 构造函数调用后

The code that uses this particular constructor:

    private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        AisleSelection aisleSelect = args.NewValue as AisleSelection;
        if (aisleSelect.Partitions == null)
            aisleSelect.Partitions = new PartitionCollection();
        else
            aisleSelect.Partitions = new PartitionCollection(aisleSelect.Partitions);
    ...
    }

Essentially what I'm trying to do is replace the ObservableCollection with my PartitionCollection which overrides a few key members. The ObservableCollection is passed down to me from the server in serialized form, so there is no way I can use it directly.

If I understand your question correctly you want to replace on observable collection with another but you still want subscribers to events on the old collection to be notified when the new collection changes.

If that is correct what you want is to keep the old collection synchronized with the new collection. The new collection should keep an reference to the old (source) collection and whenever the new collection is modified you perform the same modification on the old collection.

In PartitionCollection you can override ClearItems , InsertItem , RemoveItem and SetItem and forward the changes to the old collection after calling the base class implementation of the methods in the new collection. This should keep the synchronized.

If you absolutely only want a sinlge copy of the collection you can derive PartitionCollection from IObservableCollection<AislePartition> and provide you own implementation of the interface. The backing store for this collection should then be the old collection. This solution is quite tedious because you have to implement a lot of methods that simply are forwarders to the same methods on the wrapped collection but you would ensure that the collection wasn't copied.

If the old collection could be modified by other means than through your wrapper you will have to subscribe to changes on the old collection and fire similar events from the wrapper.

There are some "evil" tricks that may allow you to get access to the invocation list of the old collection if you really want to. However, I would think twice before doing that.

You can't just copy the event handlers from one object to another object because events provide just two methods to add a handler and remove a handler... in other words you can't enumerate the handlers and add them to your new object event.

What I'd suggest would be to make a weak (or strong) to the old object and provide an internal event handler that invokes first all the subscribers of your event and then invokes the event on the provided object.

Keep in mind that if you use a strong reference the old object will be kept alive as long as the current object is alive, so that could potentially lead to memory leaks or excessive memory usage.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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