I'm developing a winforms app with lots of different forms and user controls. Is there a recommended pattern that I could implement that notifies the user that there are unsaved changes on the current form/control when the form/control is exiting and also when the app is closing?
Memento is a way to encapsulate undoable changes.
You can then keep a log of your uncommitted memento instances.
But that's usually way to complex.
State is usually best.
Your application has two "change" states: Saved All Changes, Unsaved Changes.
Each State has a transition rule based on "change" and "save" methods.
The Saved All Changes implementation of "save" does nothing.
The Unsaved Changes implementation of "save" sets the state to "Saved All Changes".
The Saved All Changes implementation "change" sets the state to Unsaved Changes.
The Unsaved Changes implementation of "change" does nothing.
I'm using LLBL Gen pro for the ORM so that has some good entity tracking built into the objects. I've kind of rolled my own that seems to work pretty well. I created a new interface that my base User Controls and base Forms implement:
public interface IClosingNotification
{
/// <summary>
/// True if there is a dirty entity (or a dirty entity in the collection) present
/// </summary>
bool DirtyEntityPresent { get; }
/// <summary>
/// Register an entity to be watched for changes
/// </summary>
/// <param name="entity"></param>
void RegisterForClosingNotification(IEntity entity);
/// <summary>
/// Register a collection to be watched for changes
/// </summary>
/// <param name="collection"></param>
void RegisterForClosingNotification(IEntityCollection collection);
/// <summary>
/// Returns true if the form should close without any notification
/// </summary>
/// <returns></returns>
bool ShouldClose();
}
In my base control/form I have a collection of entities that I watch on each form, and I have a CloseForm() method in these classes that I use when a form is closing. In my forms, whenever I create an object I can then register it for closing notification using: RegisterForClosingNotification(MyCustomer);
It works well in our scenario.