MVVM RelayCommand CanExecute

9

我正在使用一个RelayCommand来实现执行和可执行操作。当没有canExecute部分时,RelayCommand可以工作,但是当我添加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; }

你能发布一下你正在使用的“RelayCommand”的实现吗? - Rohit Vats
@RohitVats,RelayCommand的实现如上所示,您是在谈论XAML部分吗? - JonasN89
3
请确保使用CommandWPF命名空间,因为在Command命名空间中RelayCommand的CanExecute功能存在问题。请参考http://blog.jsinh.in/relay-command-canexecute-not-working-using-mvvmlight-toolkit-in-wpf/#.VYGoOvnmv30。 - reggaeguitar
4个回答

16

由于在 .NET 4.5 更新后,CommandManager 不再触发can execute检查,因此 MVVMLight 经历了一段时间的中断。这个问题已经解决。现在你应该使用 GalaSoft.MvvmLight.CommandWpf 命名空间,而不是包含 GalaSoft.MvvmLight.Command 命名空间。在该命名空间中定义的 RelayCommand 仍然会检查传递给命令的 CanExecute 函数。

我花了一天的时间才找出我的应用程序出了什么问题。希望这篇文章能对你们有所帮助。

这里 是开发者的博客文章,解释了为什么需要这样做。


3
谢谢!因为你的回答,我不用再寻找一天了 ;) - Björn Boxstart
1
即使直接调用CanExecute方法也没有帮助。更改命名空间使其正常工作。 - user6490459
1
我找了一天,然后找到了这个答案!谢谢! - mins

6

由于某种原因,您需要执行以下操作:

public RelayCommand RedoCommand{
     get;
     set;
}

您可以根据您的访问级别,在“set optional”之前加上“private”。然后执行:
RedoCommand = new RelayCommand(() => undoRedoController.Redo(), () => undoRedoController.CanRedo());

现在您可以调用RedoCommand.RaiseCanExecuteChanged()方法,一切都能正常工作。

1
当我尝试运行那个示例时,编译器会报错。如果在RelayCommand ctor中删除"() =>"并且在方法名称后面删除括号,则可以正常工作。 - reggaeguitar
好的,我无法解释那个。我已经让上面的代码工作了。如果有帮助,请点赞 :) - JTIM
1
可能是MVVM Light的版本问题,不太确定。 - reggaeguitar
7
请确保你正在使用CommandWPF命名空间,因为在Command命名空间中,RelayCommand的CanExecute功能存在问题。请参见http://blog.jsinh.in/relay-command-canexecute-not-working-using-mvvmlight-toolkit-in-wpf/#.VYGoOvnmv30。 - reggaeguitar

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

3
.RaiseCanExecuteChanged() 是 Prism 的 DelegateCommand 库中的一部分,而不是 RelayCommand - Aron
@tsiorn 不,我没有执行 RedoCommandRaiseCanExecuteChanged(),这是我必须自己实现的函数吗?如果是,怎么实现? - JonasN89
@Aron 我正在使用MVVMLight,所以我必须自己创建.RaiseCanExecuteChanged()并将其添加到RelayCommand中吗? - JonasN89
@JonasN89 你不需要实现它。当你在RelayCommand上调用RaiseCanExecuteChanged()方法时,你的CanExecute方法(CanRedo)将被调用。每当你添加或删除你正在维护的重做堆栈时,你应该调用RaiseCanExecuteChanged()。 - tsiorn
@tsiorn 可能没有表达清楚,但我创建 RelayCommand 的部分在一个不同的类中,而我创建 Redo 和 CanRedo 的 voids 的部分在另一个类中。所以我找不到 UndoCommand。还有,是否有一些库需要添加才能得到 RaisedCanExecuteChanged() 部分,因为到目前为止它没有出现。 - JonasN89
显示剩余3条评论

1

我没有触发CanExecuteChanged事件,所以我必须实现CanExecuteChanged并将其添加到我的RelayCommand中。我正在使用MVVMLight。 - JonasN89
请参阅以下链接: link - Califf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接