Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undo Redo in WPF/C# in an already functional application

I have done some research already as to how I can achieve the title of this question. The app I am working on has been under development for a couple of years or so (slow progress though, you all know how it is in the real world). It is now a requirement for me to put in Undo/Redo multiple level functionality. It's a bit late to say "you should have thought about this before you started" ... well, we did think about it - and we did nothing about it and now here it is. From searching around SO (and external links) I can see that the two most common methods appear to be ...

Command Pattern

Memento Pattern

The command pattern looks like it would be a hell of a lot of work, I can only imagine it throwing up thousands of bugs in the process too so I don't really fancy that one.

The Memento pattern is actually a lot like what I had in my head for this. I was thinking if there was some way to quickly take a snapshot of the object model currently in memory, then I would be able to store it somewhere (maybe also in memory, maybe in a file). It seems like a great idea, the only problem I can see for this, is how it will integrate with what we have already written. You see the app as we have it draws images in a big panel (potentially hundreds) and then allows the user to manipulate them either via the UI or via a custom built properties grid. The entire app is linked up with a big observer pattern. The second anything changes, events are fired and everything that needs to update does. This is nice but I cant help thinking that if a user is entering text into a texfield on the properties grid there will be a bit of delay before the UI catches up (seems as everytime the user presses a key, a new snapshot will be added to the undo list). So my question to you is ....

  • Do you know of any good alternatives to the Memento pattern that might work.
  • Do you think the Memento pattern will fit in here or will it slow the app down too much.
  • If the Memento pattern is the way to go, what is the most efficient way to make a snapshot of the object model (i was thinking serialising it or something)
  • Should the snapshots be stored in memory or is it possible to put them into files?

If you have got this far, thankyou kindly for reading. Any input you have will be valuable and very much appreciated.

like image 561
DrLazer Avatar asked Dec 28 '22 04:12

DrLazer


2 Answers

Well , Here is my thought on this problem.

1- You need multi level undo/redo functionality. so you need to store user actions performed which can be stored in a stack.

2- Your second problem how to identify what has been changed by a operation i think through Memento pattern , it is quite a challenge. Memento is all about toring initial object state in your memory.

either , you need to store what is changed by a operation so that you can use this information to undo the opertions.

Command pattern is designed for the Undo/Redo functionality and i would say that its late but its worth while to implement the design which is being used for several years and works for most of the applications.

like image 149
TalentTuner Avatar answered Jan 05 '23 15:01

TalentTuner


If performance allows it you could serialize your domain before each action. A few hundred objects is not much if the objects aren't big themselves.

Since your object graph is probably non trivial (i.e. uses inheritance, cycles,...) the integrated XmlSerializer and JsonSerializers are out of question. Json.net supports these, but does some lossy conversions on some types (local DateTimes, numbers,...) so it's bad too.

I think the protobuf serializers need either some form of DTD(.proto file) or decoration of all properties with attributes mapping their name to a number, so it might not be optimal.

BinaryFormatter can serialize most stuff, you just need to decorate all classes with the [Serializable] attribute. But I haven't used it myself, so there might be pitfalls I'm not aware of. Perhaps related to Singletons or events.

like image 38
CodesInChaos Avatar answered Jan 05 '23 14:01

CodesInChaos