ICommand is not refreshing CanExecute

Jun 15, 2011 at 10:02 PM

Sanjay,

I see that you implemented "event EventHandler ICommand.CanExecuteChanged" in the UndoableDelegateCommandBase class.  Very thorough.  Thanks.

However, I have replicated your example with a twist and the CanExecurteChanged does not work.  I have Save and Cancel buttons.  When the user clicks Save or Cancel then I create a new UndoRedoContext, new UndoCommand and new RedoCommand, but they do not refresh in my WPF View.  I find this to be a puzzle.  Can you help me?

What did you intend for the scenario where the user clicks Save or Cancel?  How would I clear the stacks and refesh the button commands?

Joe

Coordinator
Jun 16, 2011 at 1:17 AM

undo/redo is really an orthogonal concept to save/cancel. For example, in Word you can undo and redo even if the document you're editing is not saved. 

Two solutions come to mind for your problem:

In my simple example I only had View and ViewModel, but not a Model. Usually what you do is your datas in the Model, UI is in the View and the (testable) brains are in the ViewModel. Models exist solely for persistance (at least the way I usually implement it).

So lets say you have this simple class:

 


public class CustomerModel {
	[Some data properties here]
	[Some methods to do with saving this Customer here]
	[Possibly some methods to do validation (some people prefer doing this in the ViewModel or both)]
}

 

You'd have a corresponding ViewModel class as follows:

 


 

public class CustomerViewModel : ViewModelBase {
[An instance of the Model]
[some observable(/undoable) properties here corresponding to the data properties in the Model above]
[A 'Save' ICommand that writes all corresponding properties from the ViewModel to the instance of the Model]
[A 'Cancel' ICommand that reads all corresponding properties from the Model and writes them to the instance of the ViewModel]
}

Sorry about the weirdly written example :).

The confusion in MVVM that often arises is that a ViewModel might be doing one of two jobs (or a combination of the two). 
It might be adapting the View to the state of the data (like validation), or it might be adapting the Model to the state of the data (like saving).
Let me know if you need a clearer code example ...
Jun 16, 2011 at 1:45 AM

Thanks Sanjay.  You have described my implementation pattern.

I am building a complex WPF app, one piece at a time.  There will be lots of navigations, using Prism.  So I have Views with Undoable properties.  The Undo/Redo commands work fine.  But when I click my Save button the Undo and Redo buttons are incorrectly enabled.  For example, I test by opening the View, changing an undoable property, clicking Undo, clicking Redo, and clicking Save.  Maybe it's just me, but I want the Undo and Redo to reset to a new baseline after Save or Cancel.  So I want the Undo and Redo buttons disabled, just like at the beginning.  But they stay enabled.  So I tried, in my Save method, setting the undocontext = null, create a new undocontext, create new Undo and Redo buttons.  Still, the buttons appear to retain statefulness!  I cannot understand.  In the debugger I see new objects, but in the View I see the button enabled the same as before I clicked Save.  So, maybe my question is not even about the UndoRedo Framework.  Maybe my question is about WPF.  WTF WPF!  How can I get the Command.CanExecute to refresh?  I even created new Command objects and set them to my public properties.

Does your framework send PropertyChanged events for the Commands and their CanExecute bits?

Joe