actually I was facing the below exception when I try to update the collection outside the UI thread in my WPF app. But found the dispatcher solution to fix the exception.
But my collections are actually dependent on each other. When I updates one collection based on the newly added data I will update my another collection. But when I use the below code, my collections are not updating properly. Please assist me to fix this
class Class1
{
// UI thread
ObservableCollection<string> myCollection1 = new ObservableCollection<string>();
ObservableCollection<string> myCollection2 = new ObservableCollection<string>();
object lockObject1 = new object();
object lockObject2 = new object();
public Class1()
{
syncCollection();
}
public void syncCollection()
{
BindingOperations.EnableCollectionSynchronization(myCollection1, lockObject1);
BindingOperations.EnableCollectionSynchronization(myCollection2, lockObject2);
}
// Assume that the below methods are being called by Non UI thread
//After Collection2 is updated this method will be called from the NON UI THREAD
//If Foo is added in collection2 then add Bar in collection1
public void UpdateCollection1()
{
if (myCollection2.Contains("Foo"))
{
Application.Current.Dispatcher.BeginInvoke((Action)delegate
{
myCollection1.Add("Bar");
});
}
}
//This method will be called first from the NON UI THREAD
public void UpdateCollection2()
{
Application.Current.Dispatcher.BeginInvoke((Action)delegate
{
myCollection2.Add("Foo");
});
}
}
In the above sample code, I want add "Bar" inside Collection1 only when the Collection2 has "Foo". But when we run the code the "if" condition fails(means that collection2 doesn't have "Foo" in it).
EDIT1:
- I have a view(xaml) where an Itemsource is an ObservableCollection. That OC is in a datamodel.
- One of the feature in the app is to add new items to the itemsource which is the OC
- To add new items in the OC I had to enable the synchronization to when its updating from UI thread, so I use EnableCollectionSynchronization & dispatcher.
- Now the problem is, I have multiple ObservableCollection itemsources and they are dependent. When I apply the same with all the OCs the expected item is not adding
EDIT2 I tried to add the code replica
class ViewModel1 : INotifyPropertyChanged
{
protected ObservableCollection<Datamodel1> _items;
public ObservableCollection<Datamodel1> Items
{
get
{
return _items;
}
set
{
SetProperty<ObservableCollection<Datamodel1>>(ref _items, value);
}
}
public void Set(Items obj)
{
BindingOperations.EnableCollectionSynchronization(obj.ItemSource1, _lock1);
Items = obj.ItemSource1;
}
}
class ViewModel2 : INotifyPropertyChanged
{
protected ObservableCollection<Datamodel2> _items;
public ObservableCollection<Datamodel2> Items
{
get
{
return _items;
}
set
{
SetProperty<ObservableCollection<Datamodel2>>(ref _items, value);
}
}
public void Set(Items obj)
{
BindingOperations.EnableCollectionSynchronization(obj.ItemSource1, _lock2);
Items = obj.ItemSource2;
}
}
class Items
{
public ObservableCollection<Datamodel1> ItemSource1 = new ObservableCollection<Datamodel1>();
public ObservableCollection<Datamodel2> ItemSource2 = new ObservableCollection<Datamodel2>();
}
class ParentDatamodel
{
public string ParentProperty { get; set; }
public string ParentProperty2 { get; set; }
}
class Datamodel1 : ParentDatamodel
{
public string MyProperty { get; set; }
public string MyProperty2 { get; set; }
}
class Datamodel2 : ParentDatamodel
{
public string MyProperty { get; set; }
public string MyProperty2 { get; set; }
}
//This methods are called outside the UI thread
class Updater
{
public Items items { get; set; }
public void updaterForDatamodel1()
{
Application.Current.Dispatcher.BeginInvoke((Action)delegate
{
items.ItemSource1.Add(new Datamodel1() { MyProperty = "Foo" }) ;
});
}
public void updaterForDatamodel2()
{
if(items.ItemSource1.Any(x => x.MyProperty == "Foo")) //This condition is getting failed
{
Application.Current.Dispatcher.BeginInvoke((Action)delegate
{
items.ItemSource2.Add(new Datamodel2() { MyProperty = "Bar" });
});
}
}
}