Tracking the changes (create, update, delete) in an
ObservableCollection so that they can be saved to a disconnected backing store is not directly supported by the collection, and the solution is not immediately obvious. This can be an issue in multitier applications. Presented here is a class to handle the tracking, providing three lists of changes:
This is demonstrated in a small sample application which displays an
ObservableCollection in a WPF
DataGrid control. As the user adds, updates, and deletes rows, the
ChangeTrack class tracks the changes, and presents the three lists in three additional
DataGrid controls when the user clicks the
ChangeTrack class does additional logic to minimize overlapping changes to the backing store. For example, if a row is added, but then deleted before saving to the backing store, the row is eliminated from both lists (
RowsDeleted), since no change to the backing store is needed in such a case. The unit tests exercise all seven combinations of create, update, and delete.
Using the code
ChangeTrack class is the heart of this solution. Once the
ObservableCollection is initially loaded, it is passed to an instance of
ChangeTrack, which commences tracking any changes. The class exposes three lists,
RowsDeleted, as public properties. As the collection is changed, these lists are kept up to date. After the changes are committed to the backing store, the program should call the
ClearTracking method to clear the lists. At this point, any new changes will continue to be tracked. When the change tracking is no longer needed, the
Dispose() method should be invoked to release the event handlers.
The setup is simple. The creation of the
ChangeTrack instance requires the same
Type of the row class held by the
ObservableCollection. In the example, the row class is named "
ObservableCollection<Data> Rows; ChangeTrack<Data> changeTrack = new ChangeTrack<Data>();
ObservableCollection is initially loaded, pass it to the
StartTracking method of the
ChangeTrack class to start tracking changes.
There is also a
HasChanges property that can be used to signal, for example, a
RoutedUICommand, that is true when any changes have occurred.