Easly cancellable operations WPF Several times we need to be able to revert the data the user is inserting to a previous state (cancel data update). In order to keep DRY and for the sake of separation of concerns I thought about a way of just allowing that.

public class RevertableObject&lt;T&gt; : ViewModelBase //implements INotifyPropertyChanged
    where T:class, ICloneable
{
    public RevertableObject(T initialValue)
    {
        Value = initialValue;
        Value = initialValue.Clone() as T;
    } 

    private T _oldValue;
    private T _currentValue;
    public T Value
    {
        get { return _currentValue; }
        private set
        {
            _oldValue = _currentValue;
            _currentValue = value;
            OnPropertyChanged();
        }
    }

    public void Revert()
    {
        Value = _oldValue;
    }
}


Some drawbacks of this solution are, but are not limited to:


Dependency on the interface ICloneable which does not have a way of knowing the cloning algorithm being used (member clone vs deep clone)
It only allows one object to be reverted once.


Any insights of better alternatives? Is this code acceptable?
You could empower IEditableObject. Here is a good article. Approach described will allow your model to do not mix concerns - they use memento design pattern.

UPDATE: I do not feel right by copy-pasting that article, so I would still recommend to have a look at it. Quick test though might look like the following:

1) Download and reference BindingOriented.Adapters project in your WPF application.

2) Create model:

public class Contact
{
    public string Name { get; set; }
}


3) Create view model (I used MvvmLight for RelayCommand):

public class MainViewModel 
{        
    public MainViewModel()
    {
        Contact = new EditableAdapter&lt;Contact&gt;(new Contact() { Name="Dmitry" });
        OKCommand = new RelayCommand(() =&gt; Contact.EndEdit());
        CancelCommand = new RelayCommand(() =&gt; Contact.CancelEdit());
    }

    public EditableAdapter&lt;Contact&gt; Contact { get; }
    public ICommand OKCommand { get; }
    public ICommand CancelCommand { get; }
}


4) Update MainWindow to include:

&lt;StackPanel&gt;
    &lt;StackPanel.DataContext&gt;
        &lt;vm:MainViewModel/&gt;
    &lt;/StackPanel.DataContext&gt;
    &lt;TextBox Text="{Binding Contact.Name}"/&gt;
    &lt;Button Content="OK" Command="{Binding OKCommand}"/&gt;
    &lt;Button Content="Cancel" Command="{Binding CancelCommand}"/&gt;
&lt;/StackPanel&gt;


It works :)