Using BindingOperations.EnableCollectionSynchronization
All the examples I've seen on Stack Overflow for this get it wrong. You must lock the collection when modifying it from another thread.
On dispatcher (UI) thread:
_itemsLock = new object();
Items = new ObservableCollection<Item>();
BindingOperations.EnableCollectionSynchronization(Items, _itemsLock);
Then from another thread:
lock (_itemsLock)
{
// Once locked, you can manipulate the collection safely from another thread
Items.Add(new Item());
Items.RemoveAt(0);
}
More information in this article: http://10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux
I am not sure if this will help but still you can give it a try.
Add a Property
in Debugger
which will hold the Collection
from BL
like
private ObservableCollection<string> _data = new ObservableCollection<string>();
private object _lock = new object();
public ObservableCollection<string> Data { get {return _data;} }
In the constructor just add the below line
BindingOperations.EnableCollectionSynchronization(_data, _lock);
this will above line will take care of thread safety.
Below is the example
ViewModel (Debugger
)
internal class ViewModelClass : INotifyPropertyChanged
{
private object _lock = new object ();
private ObservableCollection<string> _data;
public ObservableCollection<string> Data
{
get { return _data; }
private set
{
_data = value;
RaisePropertyChanged ("Data");
}
}
private string _enteredText;
public string EnteredText
{
get { return _enteredText; }
set
{
_enteredText = value;
_data.Add (value); RaisePropertyChanged ("EnteredText");
}
}
private void RaisePropertyChanged (string name)
{
var pc = PropertyChanged;
if (pc != null)
pc (this, new PropertyChangedEventArgs (name));
}
public ViewModelClass ()
{
var _model = new ModelClass ();
Data = _model.Data;
_data.CollectionChanged += (s, e) => RaisePropertyChanged ("Data");
}
public event PropertyChangedEventHandler PropertyChanged;
}
Model(BL
)
internal class ModelClass
{
private ObservableCollection<string> _data;
public ObservableCollection<string> Data
{
get { return _data; }
private set { _data = value; }
}
public ModelClass ()
{
_data = new ObservableCollection<string> { "Test1", "Test2", "Test3" };
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
this.DataContext = new ViewModelClass ();
}
}
MainWindow.xaml
<Window x:Class="CollectionSynchronizationTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<StackPanel>
<ComboBox IsEditable="True"
ItemsSource="{Binding Data}"
Text="{Binding EnteredText, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<Button Content="Test" />
</StackPanel>
When the window loads just enter "SomeValue" in the ComboBox
and then after pressing the Tab
key you should find the new value in the ComboBox
dropdown