I was under an assumption that ObservableCollection<T> works perfect with WPF DataGrid until my friend wannabeegeek came up with a strange problem. The problem was making ObservableCollection<T> update the ItemSource on fly while editing them. What’s the big deal right? Wrong.
If you are using MVVM you do not want to wire up the event on DataGrid for an updated source. You will very much think that as long as you bind the collection to the ViewModel’s property and the mode is set to TwoWay – the source is updated automatically when items are edited in the DataGrid.
Your ViewModel will fire the property changed when the collection itself changes – that is if you replace the property itself. So if you want to know the change in items of the collection you need to subscribe to the CollectionChanged event of the ObservableCollection<T> property in your ViewModel.
Occurs when an item is added, removed, changed, moved, or the entire list is refreshed.
But there is a problem with ObservableCollection.CollectionChanged event – it does not fire when your data item’s property changes. It fires only if the entire item is replaced. That is if you have a collection of an Entity “Expense” that has properties “Name” and “Amount” and if you simply change the Amount value in the grid it does not work! You need to replace the entire “Expense” object for you to see the collection change firing up.
.. and the screen shot:
I have a DataGrid that is simply bound to an “BindingList<Expense>”. Right below that I have a Total that is bound to the “TotalExpense” property. Now here is what I wanted to do – Whenever user edits the amount in the Grid the Total should be calculated as he/she tabs out.
.. and the ViewModel with the solution:
The TotalExpense getter simply calculates the sum. And the ListChanged event of Expenses property simply notifies the change in TotalExpense.
.. and in the View:
Download the full code here. The code contains a tiny MVVM framework(inside core folder). – Read the disclaimer of the blog before you play with my code.
If you know to achieve this exact behavior with ObservableCollection do make a comment to this post and let me know!