修理済み!
nemesvFooCommand.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の作業項目をDispatcher作業項目 キューに配置します。作業項目は、すべてのハンドラーにイベントを通知することになっています。Background
CommandManager.RequerySuggested
問題は、この作業項目が実行されないことです。
解決策は、ディスパッチャに作業項目の実行を強制することです。
MVVMFoundationCodePlexページのこのディスカッションで解決策を見つけました。私はなんとかコードを次のヘルパークラスにいくらか単純化することができました。
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);
そして、最も重要なことに、それは合格します:)