Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement 'undo' operation in .net windows application?

Assume that, a win form has certain input fields and user enters/re-enters some data.

How to retain data previously entered by 'undo' operation?

Just I want to know the best way to accomplish it.

like image 953
Dhanapal Avatar asked Apr 29 '09 05:04

Dhanapal


3 Answers

There are a few options. The important thing is that you start designing it in early in the project. Trying to add it to an existing project can be very expensive if it wasn't designed with this capability in mind.

There are a few fundamental patterns that you'll want to take advantage of:

  1. MVC or Observer pattern. The first key isn't so much the religious or pattern-zealot implementation of your high-level architecture. What is important is that your software recognizes the difference between its current state and the displayed state, and decouples appropriately. There needs to be a common, clearly-defined coupling between your visual state and your application state. This provides you with the common architecture you need to create a command (see #2).

  2. The Command pattern. You get a lot of quality with the command pattern (though it can come at the cost of some code that looks like it should be wizard-generated). The specific approach you take to the command pattern may vary (one class per command with implementation via overrides versus one class per many commands with implementation via event handlers, e.g.), but commands are the "action" class that @Ralph suggested structuring a stack around.

    This can be a bit tricky, but the general approach would be to listen for an event that would "commit" data from the visual state to the app state. The Validated event might be a good hook for a Textbox. The Click event would make more sense for a Button. When that commit happens, you create the command associated with that control, you attempt to execute the command, and you add the command to your undo stack if the command completes successfully. Now you're tracking exactly what's happening and exactly the data it's happening with.

  3. The Memento pattern. @JP Pulled out the last piece of the puzzle. You can use a memento on the saved command to store what the affected control's state was before the command executed. This, combined with an UnExecute() member on your command's interface, should be the last core piece of design you need to perform your task.

The nice thing about a structured approach like this is that you now have a natural extension point for additional behavior that needs to happen on a command-basis. Transactions are a natural fit, for example. In my current project, I'm using the WPF ICommand interface (in my winforms project) to provide feedback about whether a given command CanExecute() at any given time. This lets me enable and disable UI widgets appropriately in a purely command-driven way. :)

The unfortunate thing is that there isn't a lot of support for this structure built-in to Winforms (as far as I know), so you'll need to build most of it from scratch. No single piece is particularly complicated, but you can find yourself generating a fair amount of mostly-boilerplate code for each command. It's also a pervasive design technique. For it to be effective, it has to be used consistently throughout the appropriate portions of the application. This makes retrofitting the functionality pretty expensive, especially if the original code is tightly coupled and incohesive.

like image 156
Greg D Avatar answered Nov 09 '22 15:11

Greg D


I'm not sure if WinForms/.Net has some type of built-in Undo feature that you can take advantage of. But what you are really looking for is a Stack datastructure to help you manage a list of actions. You'll need to create some type of "action" object to represent the actions that a user could do and as they progress through the application you'll need to push these actions onto the Stack. When they hit the undo button, or Ctrl-Z or whatever method of initiating the undo action you'll pop off the current action and restore the application state to the previous action.

This is a very basic and high level overview of how this would work but I imagine that implementing such a feature can get quite complex. Just imagine how it needs to work for a program like Adobe Photoshop. :O

like image 3
Ralph Caraveo Avatar answered Nov 09 '22 15:11

Ralph Caraveo


This might not be the best way to go about it depending on what you're trying to accomplish, but you could use a richtextbox and call upon the undo method built into that control.

For example:

richTextBox1.Undo();
like image 2
THE DOCTOR Avatar answered Nov 09 '22 14:11

THE DOCTOR