Reputation: 19122
I am working on an MVVM-based WPF app that uses the DataGrid
. The grid is data-bound to an ObservableCollection<Widget>
(the Widget
list). The user needs to be able to insert a Widget
into the list below the currently-selected Widget
, to delete a selected Widget
, and to reorder the Widget
s on the grid. I'll implement the reordering through dragging and dropping.
Before I dig into this, I want to get a reality check on my approach. Here is what I am planning to do: The Widget
class will have an Index
property that will be used to order the Widget
list. Additions, deletions, and reordering will be done by manipulating this Index property, and sorting will be done on the Widget
list, rather than through a CollectionView
.
Before the DataContext
is set, the Widget
list will be sorted on the Index
property. When a user adds a Widget
, the Index
property will be incremented by 1 for each Widget
below the selected item on the grid, and the new Widget
will be given the index number opened up by the renumbering. The Widget
list will resorted, and the bindings will be refreshed.
When a user deletes a Widget
, the Widget
will be removed from the list, and the Index
property of items on the grid below the deleted item will be decremented by 1. The Widget
list will be resorted, and the bindings refreshed, as above. Reordering will be done as a combination delete-and-insert.
Here is my question: Is this a reasonable strategy for implementing inserting, deleting, and reordering? Is there a better way to go about it? Any good articles or blog posts on the subject? I've looked, but I'm not coming up with anything on-point.
Thanks for your help.
Upvotes: 1
Views: 2316
Reputation: 19122
I've got this problem figured out. I do need the Index property, but I don't need to sort the ObservableCollection. I create an interface, IIndexedObject, with one property, Index. I implement that interface on any object that needs to be indexed, and in my database table, I add an Index column.
When I load into my object model, I sort the database table on the Index property. That ensures that the list is loaded in the same order as in the last run. I add objects using the blank row provided at the bottom of the DataGrid. It gives them an index of 0. I delete objects using a Delete button bound to an ICommand in the view model.
My view model subscribes to the CollectionChanged property of any ObservableCollection that contains IIndexedObjects. When the event fires, the view model passes the collection to a ReIndexCollection service method, which takes an IIndexedObject. The method re-indexes the collection, based on its current order, by simply iterating the collection, assigning an incremental integer value to each element's Index property. When I persist the collection back to the database, the Index value gets saved, to ensure that the collection is loaded in the same order on the next run.
Since the only sorting that is needed is done at the database load, there is no need to sort the ObservableCollection. When I move items on the DataGrid, it will take care of re-ordering the collection at that time. All I have to do is re-index the collection, so that its order will be persisted back to the database.
All-in-all, it's much easier than I had expected. One of the reasons I like WPF and MVVM.
Upvotes: 2
Reputation: 2273
Improving sorting performance: http://blogs.msdn.com/jgoldb/archive/2008/10/30/improving-microsoft-datagrid-sorting-performance-part-3.aspx
Upvotes: 0