DataGrid and MVVM with Undo/Redo

Deadly 提交于 2019-12-03 22:45:54

2 Ways to go about this:

  1. Have your all logic on the ViewModel (POCO Models).

    You'll have to have your ViewModel contain an Undo/Redo stack. How you implement it is up to you, but I'd suggest just having the Undo/Redo stacks be of Tuple<String, Object>. Store the property name and the value of the property. It's easier than managing clones. It also gives you the ability for a poor mans "dirtiness" check by seeing if the UndoStack has any items on it.

  2. Give your models some interfaces such as IUndoRedo (Rich Models).

    You'll have to have your ViewModels call interface methods to Undo/Redo, but the idea is the same... have an Undo/Redo stack that is composed of Tuple<String, Object>.

    If you do decide to want to have a rich model approach, you can look at existing frameworks out there such as CSLA.Net which is made for rich models, though it might be a bit more than what you'll really need. Just throwing it out there in case you want to have really rich models.


A side note: You're ObservableCollection (ItemsSource) should be of ViewModels, not Models. Just throwing that out there in case you were using the Models. That is, don't do ObservableCollection<IEmployee>, but rather ObservableCollection<EmployeeViewModel>. It makes things easier, much easier and more reusable!

Another side note: try to avoid the DataGrid. It makes developers wanna rip their hair out. I'd just roll out your own "Grid" with ListView :)

Normally I build the undo logic into the models themselves. Get them completely working the way you want before you even start thinking about how they are going to be bound to the UI.

I have done an article about undo / redo in MVVM. It is divided in two parts: the first explains undo / redo in general editions and the second explains working with lists:

Part 1: Using the Viewmodel pattern to provide Undo / Redo in WPF

Part 2: Viewmodelling lists

The flow is: User action (View) -> Command (VM) -> Commmand execution modifies the Model -> Model notifies changes to VM -> VM notifies changes to the view. This way if the model is modified from other source it also refresh the view.

There is also a github project here.

Since your DataGrid is bound to a collection, you can monitor changes to the Collection itself instead of the DataGrid. Use the CollectionChanged event on your collection to watch for added or removed items, and register a PropertyChanged event on all of your collection's items for monitoring edits.

An alternative idea would also be to provide a RevertChanges command instead of UndoChanges. Its much simpler to implement because you only need to store the original collection so you can restore it if needed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!