ListBox.ItemsSource не отключается от INotifyCollectionChanged
От: Spirit_1 Россия  
Дата: 24.04.13 15:47
Оценка:
Примерно на таком коде проявилась проблема. Есть некий объект со свойством в виде коллекции ObservableCollection
    public class CollectionHolder
    {
        public CollectionHolder()
        {
            Collection = new ObservableCollection<string> { "a", "b" };
        }

        public IList<string> Collection { get; set; }
    }


Для просмотра свойств объекта и коллекции используется окно
    public class Window2 : Window
    {
        public Window2()
        {
            lb = new ListBox();
            lb.SetBinding(ListBox.ItemsSourceProperty, "Collection");
            Content = lb;
        }

        private ListBox lb;
    }


Это окно вызывается из главного окна приложения как модальное, а потом закрывается и ссылки на него не сохраняются. DataContext обнуляется. Потом объект CollectionHolder может быть модифицирован каким либо другим потоком. Тут и возникает исключение от Dispatcher.
    public class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            holder = new CollectionHolder();
            var btn = new Button();
            Content = btn;
            btn.Click += Click;
        }

        private CollectionHolder holder;
        private int i;

        private void Click(object Sender, RoutedEventArgs E)
        {
            if (i == 0)
            {
                var win2 = new Window2 { DataContext = holder };
                win2.ShowDialog();
                win2.DataContext = null;
                GC.Collect();
                i = 1;
            }
            else
            {
                ThreadPool.QueueUserWorkItem(_ =>
                {
                    holder.Collection.Add("c"); // Exception !
                });
                i = 0;
            }
        }


Если вместо ObservableCollection применить свой класс
    public class MyList<T> : List<T>, INotifyCollectionChanged, INotifyPropertyChanged
    {
        public event NotifyCollectionChangedEventHandler CollectionChanged
        {
            add { collectionChanged += value; }
            remove { collectionChanged -= value; }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private NotifyCollectionChangedEventHandler collectionChanged;
    }

то видно, что при байндинге в event NotifyCollectionChangedEventHandler вызывается add к методу из ListCollectionView. При установке DataContext ListBox или окна в null или другой объект или очистке байндинга у ListBox.ItemsSource remove никогда не вызывается. Как же тогда отцепить коллекцию, реализующую INotifyCollectionChanged от ListBox ?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.