CommandManager.InvalidateRequerySuggested不会触发RequerySuggested

时间:2013-06-24 07:01:59

标签: c# .net wpf mvvm icommand

我正在尝试测试使用CommandManager.RequerySuggested的类,并注意到调用CommandManager.InvalidateRequerySuggested不会从我的测试中激活RequerySuggested。这有什么原因以及如何解决这个问题? CommandManager是否需要初始化?

重现问题的代码:

[Test]
public void InvalidateRequerySuggested_TriggersRequerySuggested()
{
    bool triggered = false;
    CommandManager.RequerySuggested += (s, a) => triggered = true;

    CommandManager.InvalidateRequerySuggested();
    Thread.Sleep(1000); // Just to be sure

    Assert.True(triggered); // Never true
}

3 个答案:

答案 0 :(得分:3)

正如msdn here所述,CommandManager.RequerySuggested仅包含一个弱事件引用。在你的单元测试中,lambda表达式被垃圾收集。

尝试以下方法:

bool triggered;
EventHandler handler = (s, e) => triggered = true;
CommandManager.RequerySuggested += handler;
CommandManager.InvalidateRequerySuggested();
GC.KeepAlive(handler);
Assert.IsTrue(triggered);

<强>更新

通过进一步的调查,我相信我已经找到了问题。

CommandManager.InvalidateRequestSuggested()使用当前的调度程序异步引发事件。

这是一个解决方案:

bool triggered;
EventHandler handler = (s, e) => triggered = true;
CommandManager.RequerySuggested += handler;
CommandManager.InvalidateRequerySuggested();

// Ensure the invalidate is processed
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => { }));

GC.KeepAlive(handler);
Assert.IsTrue(triggered);

答案 1 :(得分:1)

此行为的另一个可能原因:我发现我们需要使用与调用RequerySuggested的调度程序相同的调度程序订阅InvalidateRequerySuggested事件。

我在订阅此事件的非UI线程上创建了一些对象,但事件没有被引发。改变

CommandManager.RequerySuggested += HandleRequerySuggestedSuggested;

Application.Current.Dispatcher.Invoke((Action)(() => 
    CommandManager.RequerySuggested += HandleRequerySuggestedSuggested));

为我解决了。

答案 2 :(得分:0)

只需对您的事件处理程序进行强有力的引用