Reputation: 153
I have a strange behavior of the ObservableCollection in my MVVM app, more exactly in the part of the code responsible for receiving the messages from NServiceBus:
public class MyViewModel: ViewModelBase, IHandleMessages<CarMoved>
{
public ObservableCollection<CarData> Cars= new ObservableCollection<CarData>();
public Task Handle(CarMoved message, IMessageHandlerContext context)
{
...
Cars.Add(new Car());
return Task.CompletedTask;
}
}
So I expect the Handle method to add a new object into my ObservableCollection but the number of the objects remains the same. I created the test button to check whether I can add a new object using a button and this testing button works fine. I also debugged the Handle method and I can see that the number of the objects gets increased in the Observable collection while I am in the Handle method, but all that changes once I leave the method- the number of the objects returns to the old number.
I tried to add the object using Task.Run(..); Task.Wait(); presuming that maybe it needs some time. It did not help.
Please advise how I could resolve this issue and why it happens?
Upvotes: 0
Views: 105
Reputation: 169150
Make sure that you access the ObservableCollection
on the UI thread using the dispatcher:
public Task Handle(CarMoved message, IMessageHandlerContext context)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() => { Cars.Add(new Car()); }));
return Task.CompletedTask;
}
Alternatively you could try to use the BindingOperations.EnableCollectionSynchronization method to enable the collection to be accessed across multiple threads:
public class MyViewModel : ViewModelBase, IHandleMessages<CarMoved>
{
private readonly object _lock = new object();
public ObservableCollection<CarData> Cars = new ObservableCollection<CarData>();
public MyViewModel()
{
Application.Current.Dispatcher.Invoke(() => BindingOperations.EnableCollectionSynchronization(Cars, _lock));
}
public Task Handle(CarMoved message, IMessageHandlerContext context)
{
Cars.Add(new Car());
return Task.CompletedTask;
}
}
Upvotes: 0
Reputation: 71856
Ok, so the problem here is that NServiceBus will create a new instance of your ViewModel to handle the message. This is obviously not what you want.
Instead the ViewModel
and message Handler
should be separate objects. Then the handlers can tell the ViewModel
about the message.
I'm not sure what MVVM framework you're using, but usually there's some sort of event aggregator for passing messages from system components like NServiceBus handlers and ViewModels.
Upvotes: 4