我正在实现一个带有执行和canExecute部分的RelayCommand。当没有canExecute部分时,RelayCommand可以工作,但是当我添加canExecute部分时,该命令会锁定按钮。RelayCommand 只检查只要 CanExecute 部分为真,按钮是否可以执行。一旦 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; }
MVVMLight 出现了中断,因为在 .NET 4.5 更新后,命令管理器不再触发可以执行检查。这个问题已经解决了。与其包含 GalaSoft.MvvmLight.Command 命名空间,不如使用 GalaSoft.MvvmLight.CommandWpf 命名空间。在该命名空间中定义的 RelayCommand 仍在检查传递给该命令的 CanExecute 函数。
花了我大约一天的时间才找出我的应用程序中到底出了什么问题。我希望这对你们中的一些人有所帮助。
这是开发人员的一篇博客文章,解释了为什么这是必要的。
出于某种原因,您必须执行以下操作:
public RelayCommand RedoCommand{
get;
set;
}
您还可以将"设为可选"之前将"私有"设置为"可选",具体取决于您的访问级别。然后你做
RedoCommand = new RelayCommand(() => undoRedoController.Redo(), () => undoRedoController.CanRedo());
现在你可以调用RedoCommand.RaiseCanExecuteChanged();一切都正常。
如果您使用的是未修补的 .net 4.5。Microsoft打破了.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
,并且在重做堆栈更改时未引发 CanExecuteChanged 事件。
(从 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();
}