【问题标题】:How to clone the ObservableCollection<T>.CollectionChanged event?如何克隆 ObservableCollection<T>.CollectionChanged 事件?
【发布时间】:2012-08-10 15:52:15
【问题描述】:

我正在尝试将 ObservableCollection 复制到 ObservableCollection 派生类型中,并且我想保留 CollectionChanged 事件。

到目前为止,我有:

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)
    {
         // ...
    }
}

它可以很好地复制集合,但我也需要获取 CollectionChanged 事件。

有什么办法吗? 谢谢

编辑:

前: 后:

使用这个特定构造函数的代码:

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

基本上我想要做的是用我的 PartitionCollection 替换 ObservableCollection,它覆盖了一些关键成员。 ObservableCollection 是从服务器以序列化的形式传给我的,所以我无法直接使用它。

【问题讨论】:

  • “克隆事件”是什么意思?
  • 我的意思是我需要将所有处理程序复制到一个新事件中,并丢弃旧事件。在 C++ 中,this.CollectionChangedEvent = std::move(other.CollectionChangedEvent)。但这不是 C++ :(

标签: c# silverlight


【解决方案1】:

如果我正确理解您的问题,您希望将可观察集合替换为另一个集合,但您仍希望在新集合更改时通知旧集合事件的订阅者。

如果这是正确的,您想要的是将旧集合与新集合保持同步。新集合应保留对旧(源)集合的引用,并且每当修改新集合时,您对旧集合执行相同的修改。

PartitionCollection 中,您可以覆盖ClearItemsInsertItemRemoveItemSetItem,并在调用新集合中方法的基类实现后将更改转发到旧集合。这应该保持同步。

如果您绝对只想要一个集合的单一副本,您可以从IObservableCollection&lt;AislePartition&gt; 派生PartitionCollection 并为您提供自己的接口实现。这个集合的后备存储应该是旧集合。这个解决方案非常乏味,因为您必须实现许多方法,这些方法只是转发到包装集合上的相同方法,但您要确保集合不会被复制。

如果可以通过包装器以外的其他方式修改旧集合,您将必须订阅旧集合的更改并从包装器触发类似事件。

如果你真的想的话,有一些"evil" tricks 可以让你访问旧集合的调用列表。但是,在这样做之前我会三思而后行。

【讨论】:

  • 不,他正在提供另一个对象,他想将事件处理程序从另一个对象复制到构造函数中的新对象。
  • @JorgeCórdoba:但这合理吗?如果我将事件处理程序添加到 A 上的事件,然后该事件被触发但从 B 触发,这不是意外吗?我没有将处理程序添加到 B - 仅添加到 A。
  • 是的,你是对的,但这就是问题的背景。什么是“明智的”或不是真的取决于很多因素,其中大部分与里程碑、交付压力和管理压力有关:)我不是说这是一个好习惯,我说的是我的方式会解决它,但正如你所说,这样做有点奇怪。
  • 是的,我应该更好地解释我的意图,原始对象将被丢弃,我只想保留它的事件处理程序和集合项,因为我用更专业的类(PartitionCollection)替换它。 ObservableCollection 在我无法控制的其他地方被实例化。
  • 我想你理解正确,唯一的问题是我不需要旧的集合,我认为有两个副本可能会很浪费。或者可能是我误解了解决方案。来自 C++ 背景,我有一半期望 this.CollectionChanged = other.CollectionChanged 能够工作。
【解决方案2】:

您不能只将事件处理程序从一个对象复制到另一个对象,因为事件仅提供两种方法来添加处理程序和删除处理程序...换句话说,您无法枚举处理程序并将它们添加到您的新对象事件。

我的建议是对旧对象进行弱(或强)处理,并提供一个内部事件处理程序,该处理程序首先调用事件的所有订阅者,然后在提供的对象上调用事件。

请记住,如果您使用强引用,那么只要当前对象还活着,旧对象就会一直活着,这样可能会导致内存泄漏或内存使用过多。

【讨论】:

  • 听起来很有趣,但原来的对象要被销毁(我正在用新对象替换它)。最坏的情况我会这样做,因为我可以保证在整个程序中只有一个特定对象的实例。
猜你喜欢
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
相关资源
最近更新 更多