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
}
As stated on the msdn here under remarks, CommandManager.RequerySuggested
only holds a weak event reference. In your unit test the lambda expression is being garbage collected.
Try the following:
bool triggered;
EventHandler handler = (s, e) => triggered = true;
CommandManager.RequerySuggested += handler;
CommandManager.InvalidateRequerySuggested();
GC.KeepAlive(handler);
Assert.IsTrue(triggered);
Update
From some further investigation, I believe I have pinpointed the problem.
CommandManager.InvalidateRequestSuggested()
uses the current dispatcher to raise the event asynchronously.
Here is a solution:
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);