The MSDN only states that
Occurs when the CommandManager detects conditions that might change the ability of a command to execute.
However I can't seem to find any traces of how this works, what I should be aware of / avoid etc...
Does it just listen for input? (i.e.: mouse moves, keys pressed and so on)
I cannot tell you exactly what events the CommandManager
listens to. However, I can tell you that you should be careful when using the CommandManager
in connection with asynchronous operations. I had the following problem when I used the CommandManager
in my ICommand
implementations:
I had a button bound to an ICommand
which triggered an asynchronous operation which increased a value. Now, the button/ICommand
should be disabled (i.e. its CanExecute()
method should return false
) if the value had reached a certain limit. The problem was: The CommandManager
called my CanExecute()
method right after the button had been clicked and the asynchronous operation had been started. This asynchronous operation did not take long, but it was long enough to get its result after the CommandManager
's check, so that the limit check in CanExecute()
was done using the old value. Therefore, the button remained enabled although the limit was actually reached. The funny thing was, after you clicked anywhere in the UI, the button now got disabled because the CommandManager
checked the ICommand
once again and now the new value was checked against the limit.
Actually, I think the CommandManager
waited around 50ms after the button click until it performed the check of the ICommand
, but I am not quite sure about that.
My solution was to force the CommandManager
to check the ICommand
again by calling the CommandManager.InvalidateRequerySuggested
method in my ViewModel right after I received the result of the async operation.
Update: Please note that this method must be called on the UI thread, otherwise it will have no effect! (Thanks to midspace for this comment)
In that case .NET Reference Source is your friend. Although its badly commented you can still get some ideas about the internal processing.
In the internal CommandDevice class you find a method PostProcessInput which invokes the InvalidateRequerySuggested. The name of this method lets assume that the InvalidateRequerySuggested method is invoked on every input event. I'm sure there is further processing and filtering so that your CanExecute method is actually not invoked on every call to InvalidateRequerySuggested.