Well, as you said there are 3 ways. I will state them in the order I think they match MVVM best (although all are good MVVM solutions):
1) EventToCommand handles attached events (will become available in the future)
2) Call the command from code-behind
3) Use the MessageMediator
The reason I put the message mediator on the 3rd place is because I try to avoid this as much as possible. When you introduce a message mediator, some stuff becomes "magic" and you have no idea where it is coming from. This way, you create an "unknown dependency"
which the developer should be aware off. For example, there is no clear implementation that shows another developer how and when the message will be delivered by an "unknown dependency". Also, for unit testing you will need to send messages via the message
mediator to test it, which is more work than simply calling a command on a view model.
I think handling an event in the code-behind, and passing it through to the VM is much more clear (because for the VM there is no difference, the command is called). Only in the view and code-behind, there is a change, but that is easy to find simply because
the code is in the same file.
I know other frameworks such as MVVM light quickly grab to the messenger to solve such issues, but I think the message mediator should only be used for application-level communications, not as a replacement for when it becomes a bit harder to solve an issue.