2015-02-10 2 views
3

Я наблюдаю странное поведение элементов WPF ItemsControls: если для параметра ItemsSource задан объект, который реализует INotifyCollectionChanged, и после этого установите ItemsSource в null, CollectionView, который был создан для предоставления данных для ItemsControl по-прежнему прослушивает CollectionChanged -вент исходного объекта.
Если теперь исходная коллекция изменена в другом потоке, то CollectionView выдает исключение (без привязки к любому элементу управления). Хотя я понимаю, почему это происходит, я действительно застрял в разрешении этой ситуации.Как уничтожить или отсоединить CollectionView

Поэтому главный вопрос: как я могу уничтожить CollectionView так, чтобы он больше не слушал CollectionChanged -event. Или как я могу отключить его, делая это/отделяя базовую коллекцию.

Обратите внимание: описанное поведение не с ObservableCollection. Исходным объектом является IEnumerable Т и реализует INotifyCollectionChanged.

+0

ли вызова ясно() не хватает в вашем случае, вы можете установить пустой шаблон, когда граф == 0. – XAMlMAX

+0

Ясно на что? Исходный объект? – HCL

+0

вместо того, чтобы установить коллекцию в null. Извините, должен был уточнить по этому вопросу. EDIT, но я действительно помню, что есть проблема с просмотром изменений, которые меняют, когда вы вызываете метод clear в 'ObservableCollection', я найду этот пост и вернусь к вам с дополнительной информацией. – XAMlMAX

ответ

2

Вы ищете метод CollectionView.DetachFromSourceCollection():

var collectionView = CollectionViewSource.GetDefaultView(yourEnumerable) as CollectionView; 
collectionView.DetachFromSourceCollection(); 
+2

Да, точно! Но, к сожалению, кажется, что этот метод доступен только в .net 4.5, а приложение, в котором я сейчас работаю, равно 4.0. – HCL

1

Обновление Похоже, что под .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 как ItemsSource в ItemsControl. Перед настройкой затем ItemsSource на null, вызовите Detach на обертке, чтобы отменить регистрацию измененного события. Что-то следующее:

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

Обертка также может использоваться из ViewModel.

Смежные вопросы