4

I'm trying to test a class that uses CommandManager.RequerySuggested and noticed that calling CommandManager.InvalidateRequerySuggested does not fire RequerySuggested from my test. Is there a reason for this and how to I resolve this issue? Does the CommandManager require some initialization?

Code to reproduce the issue:

[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
}
4

3 回答 3

3

正如 msdn 上的备注中所述,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);
于 2013-06-24T07:11:54.020 回答
1

这种行为的另一个可能原因是:我发现我们需要使用与调用RequerySuggested事件相同的 Dispatcher 来订阅事件。InvalidateRequerySuggested

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

CommandManager.RequerySuggested += HandleRequerySuggestedSuggested;

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

为我解决了。

于 2015-01-15T10:12:24.453 回答
0

只需强烈引用您的事件处理程序

于 2013-06-24T08:57:23.933 回答