CommandManager.InvalidateRequerySuggested不会激发RequerySuggeste

本文关键字:RequerySuggeste InvalidateRequerySuggested CommandManager | 更新日期: 2023-09-27 18:19:42

我试图测试一个使用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
}

CommandManager.InvalidateRequerySuggested不会激发RequerySuggeste

如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);
这种行为的另一个可能原因是:我发现我们需要使用与调用InvalidateRequerySuggested相同的Dispatcher来订阅RequerySuggested事件

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

CommandManager.RequerySuggested += HandleRequerySuggestedSuggested;

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

为我解决了这个问题。

只需保留对事件处理程序的强引用