Примерно на таком коде проявилась проблема. Есть некий объект со свойством в виде коллекции 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 ?