MVVM RelayCommand CanExecute

时间:2013-10-14 16:01:56

标签: wpf windows-phone-8 mvvm-light relaycommand canexecute

我正在实现一个带有execute和canExecute部分的RelayCommand。 RelayCommand在没有canExecute部分的情况下工作,但是当我添加canExecute部分时,该命令会锁定按钮。只要CanExecute部分为true,RelayCommand仅检查是否可以执行按钮。一旦canExecute部分变为false,就不能再单击该按钮,即使它应该被按下。我如何确保每次点击按钮控制它是否可以执行,并且一旦无法执行就不会永久锁定它?

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; }

4 个答案:

答案 0 :(得分:10)

MVVMLight已经中断,因为在.NET 4.5更新之后,CommandManager不再触发can执行检查。这已经解决了。您应该使用GalaSoft.MvvmLight.CommandWpf命名空间,而不是包含GalaSoft.MvvmLight.Command命名空间。在该命名空间中定义的RelayCommand仍在检查传递给命令的CanExecute函数。

我花了一天的时间来了解我的应用程序到底出了什么问题。我希望这会对你们中的一些人有所帮助

答案 1 :(得分:5)

出于某种原因,您必须执行以下操作:

public RelayCommand RedoCommand{
     get;
     set;
}

您也可以在设置可选之前将其置为私有,具体取决于您的访问级别。然后你做

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

现在你可以调用RedoCommand.RaiseCanExecuteChanged(); 一切正常。

答案 2 :(得分:1)

如果您使用的是未修补的.net 4.5。微软打破了.CanExecute事件。

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

如果您正在使用http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030中的RelayCommand,并且在redoStack更改时没有引发CanExecuteChanged事件。

答案 3 :(得分:1)

(从Silverlight的角度回答,假设这会对你有所帮助。)

你在任何地方做RedoCommand.RaiseCanExecuteChanged()吗?一旦您监控的条件发生变化,您就需要手动提升此命令。

修改

因为您正在使用MVVM Light ..以下示例代码:

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();

        // At this point, your stacks have changed; that is, the stacks
        // may or may not contain items. Thus, raise the commands CanExecute part
        // which will in turn enable/disable the commands based on the functions
        // return value

        RedoCommand.RaiseCanExecuteChanged();

        // assuming you could possibly have an UndoCommand somewhere
        UndoCommand.RaiseCanExecuteChanged();
    }