Introduction
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: RowsCreated
, RowsUpdated
, and RowsDeleted
.
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 ShowChanges
button.
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 (RowsCreated
, 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
The 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, RowsCreated
, RowsUpdated
, and 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 "Data
":
ObservableCollection<Data> Rows;
ChangeTrack<Data> changeTrack = new ChangeTrack<Data>();
After the ObservableCollection
is initially loaded, pass it to the StartTracking
method of the ChangeTrack
class to start tracking changes.
changeTrack.StartTracking(Rows);
There is also a HasChanges
property that can be used to signal, for example, a RoutedUICommand
, that is true when any changes have occurred.