2013-10-14 55 views
5

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

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

你可以发布你正在使用的'RelayCommand'的实现吗? –

+0

@RohitVats RelayCommand的实现,是按照如上所示执行的,还是你在谈论xaml parrt? – JonasN89

+2

确保您使用CommandWPF名称空间,因为CommandCommandCanExecute在Command名称空间中被破坏。请参阅http://blog.jsinh.in/relay-command-canexecute-not-working-using-mvvmlight-toolkit-in-wpf/#.VYGoOvnmv30 – reggaeguitar

回答

5

出于某种原因,你必须做到以下几点:

public RelayCommand RedoCommand{ 
    get; 
    set; 
} 

你也可以把私人在设置可选之前,取决于您的访问级别。然后,你做

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

现在你能叫RedoCommand.RaiseCanExecuteChanged(); 一切正常。

+1

尝试该示例时出现编译器错误。如果在方法名称后面的RelayCommand ctor和parens中删除了“()=>”,那么它工作正常 – reggaeguitar

+0

好的,不能解释这一点。我有上面的工作。如果它是有用的,那么请投票:) – JTIM

+1

可能是MVVM Light的版本,不确定 – reggaeguitar

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#id0090030RelayCommand,而不是提高CanExecuteChanged事件redoStack变化时。

+0

我没有提出CanExecuteChanged事件,所以我必须实现CanExecuteChanged并将其添加到我的RelayCommand。我正在使用MVVMLight – JonasN89

+0

另请参阅: [链接](http://stackoverflow.com/questions/17708216/mvvm-confusion-with-canexecute-and-binding-commands) – Califf

1

(从Silverlight的角度回答这样假设这会帮助你。)

你在做一个RedoCommand.RaiseCanExecuteChanged()地方?一旦您监控变化的任何情况发生,您需要手动提高此命令。

编辑

由于您使用的MVVM光..继承人的示例代码:

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

'.RaiseCanExecuteChanged()'是一个Prism的'DelegateCommand'库的一部分不是'RelayCommand' – Aron

+1

好点。它也是MVVMLight的一部分。 – tsiorn

+0

好的。公平。但我的观点表明,它不是一个标准的类,而且OP没有指定任何库。 :) – Aron

7

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

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

+1

谢谢!因为你的回答,我不必寻找一天;) –

相关问题