3

我观察到 WPF ItemsControls 的一个奇怪行为:如果将 ItemsSource 设置为实现的对象,INotifyCollectionChanged然后将其设置ItemsSource为 null,则为CollectionView向 ItemsControl 提供数据而创建的对象仍然侦听CollectionChanged源对象的事件。
如果现在通过不同的线程更改源集合,则会CollectionView引发异常(不附加到任何控件)。虽然我理解为什么会发生这种情况,但我真的很难解决这种情况。

因此主要问题是,我怎样才能销毁 aCollectionView使其不再监听CollectionChanged-event。或者我该如何禁用它/分离底层集合。

请注意:所描述的行为不适用于ObservableCollection. 源对象是IEnumerableT 并实现INotifyCollectionChanged

4

2 回答 2

3

您正在寻找CollectionView.DetachFromSourceCollection()方法:

var collectionView = CollectionViewSource.GetDefaultView(yourEnumerable) as CollectionView;
collectionView.DetachFromSourceCollection();
于 2015-02-10T19:53:53.073 回答
2

更新 看来,在.net 4.5 下有这个所需的功能。请参阅 HighCore 的答案。对于那些没有 4.5 的人,我将解决方法留在这里,也许它可以帮助某人:

class DetachableNotifyCollectionChangedWrapper : IEnumerable, INotifyCollectionChanged {
        IEnumerable m_source;
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        public DetachableNotifyCollectionChangedWrapper(IEnumerable enumerable) {
            if (null == enumerable) throw new ArgumentNullException("enumerable"); ;
            m_source = enumerable;
            var ncc = m_source as INotifyCollectionChanged;
            if (null != ncc) ncc.CollectionChanged += SourceCollectionChanged;
        }
        void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            if (null != CollectionChanged) CollectionChanged(this,e);
        }
        public IEnumerator GetEnumerator() {
            return m_source.GetEnumerator();
        }
        public void Detach() {
            var ncc = m_source as INotifyCollectionChanged;
            if (null != ncc) ncc.CollectionChanged -= SourceCollectionChanged;
        }            
}

要使用它,请将 Wrapper 设置为ItemsSourceItemsControl 的。在将 设置ItemsSource为 null 之前,在包装器上调用 Detach 以取消注册更改的事件。如下所示:

var wrapper = m_lstLog.ItemsSource as DetachableNotifyCollectionChangedWrapper;
if (null != wrapper) wrapper.Detach();
m_lstLog.ItemsSource = null;    

包装器也可以在 ViewModel 中使用。

于 2015-02-10T19:35:40.047 回答