Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM RelayCommand CanExecute

I'm implementing an RelayCommand with an execute and an canExecute part. The RelayCommand works when it is without the canExecute part, however when I add the canExecute part, the command locks the button. The RelayCommand only checks whether or not the button can be executed as long as the CanExecute part is true. Once the canExecute part becomes false, the button can no longer be clicked, even if it is supposed to. How do I make sure that every time I click on the button it controls whether or not it can be executed, and doesn't lock it forever, once it cannot be executed?

RedoCommand = new RelayCommand(undoRedoController.Redo,undoRedoController.CanRedo);

   public bool CanRedo()
    {
        redoStack.Count();
        redoStack.Any();
        return redoStack.Any();
    }

    public void Redo()
    {
        if (redoStack.Count() <= 0) throw new InvalidOperationException();
        IUndoRedoCommand command = redoStack.Pop();
        undoStack.Push(command);
        command.Execute();
    }


 public class UndoRedoController
{
    private static UndoRedoController controller = new UndoRedoController();

    private readonly Stack<IUndoRedoCommand> undoStack = new Stack<IUndoRedoCommand>();
    private readonly Stack<IUndoRedoCommand> redoStack = new Stack<IUndoRedoCommand>();

    private UndoRedoController() { }

    public static UndoRedoController GetInstance() { return controller; }
like image 354
JonasN89 Avatar asked Oct 14 '13 16:10

JonasN89


3 Answers

There has been a hiatus with MVVMLight due to the fact that after the .NET 4.5 update the CommandManager no longer fires the can execute check. This has since been solved. Instead of including the GalaSoft.MvvmLight.Command namespace you should use the GalaSoft.MvvmLight.CommandWpf namespace. The RelayCommand defined in that namespace is still checking the CanExecute function that you pass to the command.

Took me about a day to find out what the hell was going wrong in my application. I hope this will help some of you.

Here is a blog post by the developer explanining why this is necessary.

like image 123
Jif Avatar answered Sep 20 '22 18:09

Jif


For some reason you have to do the following:

public RelayCommand RedoCommand{
     get;
     set;
}

you can also put private before set optional, depending on your access level. Then you do

RedoCommand = new RelayCommand(() => undoRedoController.Redo(), () => undoRedoController.CanRedo());

Now your able to call RedoCommand.RaiseCanExecuteChanged(); And everything works.

like image 41
JTIM Avatar answered Sep 24 '22 18:09

JTIM


If you are using an unpatched .net 4.5. Microsoft broke the .CanExecute event.

http://connect.microsoft.com/VisualStudio/feedback/details/753666/net-4-0-application-commands-canexecute-not-updating-in-4-5

If you are using the RelayCommand from http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030 and are not raising the CanExecuteChanged event when redoStack changes.

like image 30
Aron Avatar answered Sep 22 '22 18:09

Aron