固定的!
nemesv是正确的,因为它FooCommand.RaiseCanExecuteChanged()
只是调用CommandManager.InvalidateRequerySuggested()
.
除此之外,FooCommand.CanExecuteChanged
只需将处理程序转发到CommandManager.RequerySuggested
事件:
public event EventHandler CanExecuteChanged
{
add
{
...
CommandManager.RequerySuggested += value;
}
...
}
问题的原因是CommandManager类中的以下代码行:
private void RaiseRequerySuggested()
{
...
_requerySuggestedOperation = dispatcher.
BeginInvoke(
DispatcherPriority.Background,
new DispatcherOperationCallback(RaiseRequerySuggested),
null); // dispatcher is the Dispatcher for the current thread.
...
}
此行将具有DispatcherPriority Background
的工作项放置在Dispatcher工作项队列中。工作项应该通知CommandManager.RequerySuggested
事件的所有处理程序。
问题是这个工作项永远不会运行。
解决方案是强制调度程序运行工作项。
我在MVVM Foundation CodePlex 页面上的讨论中找到了解决方案。我设法将代码简化为以下帮助程序类。
public static class DispatcherTestHelper
{
private static DispatcherOperationCallback exitFrameCallback = ExitFrame;
/// <summary>
/// Synchronously processes all work items in the current dispatcher queue.
/// </summary>
/// <param name="minimumPriority">
/// The minimum priority.
/// All work items of equal or higher priority will be processed.
/// </param>
public static void ProcessWorkItems(DispatcherPriority minimumPriority)
{
var frame = new DispatcherFrame();
// Queue a work item.
Dispatcher.CurrentDispatcher.BeginInvoke(
minimumPriority, exitFrameCallback, frame);
// Force the work item to run.
// All queued work items of equal or higher priority will be run first.
Dispatcher.PushFrame(frame);
}
private static object ExitFrame(object state)
{
var frame = (DispatcherFrame)state;
// Stops processing of work items, causing PushFrame to return.
frame.Continue = false;
return null;
}
}
我的测试现在看起来像这样:
// Arrange
var canExecuteChanged = false;
viewModel.FooCommand.CanExecuteChanged +=
(sender, args) => canExecuteChanged = true;
// Act
viewModel.SomeRequiredProperty = new object();
DispatcherTestHelper.ProcessWorkItems(DispatcherPriority.Background);
// Assert
Assert.That(canExecuteChanged, Is.True);
而且,最重要的是,它通过了:)