Question

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
}
Was it helpful?

Solution

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);

OTHER TIPS

Another possible reason for this behaviour: I've found that we need to subscribe to the RequerySuggested event using the same Dispatcher as the one InvalidateRequerySuggested is called on.

I've created a few objects on a non-UI thread that subscribed to this event, and the event did not get raised. Changing

CommandManager.RequerySuggested += HandleRequerySuggestedSuggested;

to

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

solved it for me.

Just keep a strong reference to your eventhandler

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top