I've been wondering about this for a while... What's the best practice for opening a new window (view & viewmodel) from another viewmodel IF we keep in mind that the viewmodel which opens the new window is not aware of the existence of that view (as it should be).
Thanks.
I agree with a mediator-like approach, but the OnMsgReceived is clearly handled in the code-behind of the view, is there a good way to avoid this?
I don't use the ViewModel to open another View/ViewModel. This is in the responsibility of a Controller. The ViewModel can inform the Controller (e.g. via Event) that the user expects to see the next View. The Controller creates the View/ViewModel with the help of an IoC Container.
How this works is shown in the ViewModel (EmailClient) sample application of the WPF Application Framework (WAF).
Use the mediator pattern such as mvvmlight's messenger class:
http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338
The basic idea is the viewmodel sends a message to its view. The receiving view then looks like this:
This allows the viewmodel that sent the message to show another window with no 'knowledge' of how or who did the opening.
I personally prefer to either raise events in my ViewModel to signal to the view that it needs to do something like open a window. I try not to do this directly though so that I don't see things like an event named OpenWindow in my ViewModel because that seems to violate the separate between the View and the ViewModel in my opinion. Instead what I might do is have a Property that changes state and raises a PropertyChanged event accordingly in which the view may listen to and then decide to open a window in reaction to this signal. In some cases the opening of a window is not related to something in the ViewModel at all and is only a function of the View. In these cases I'm not afraid at all to place code for opening another view within the code-behind portion of the View.
The mediator pattern just makes this more loosely coupled and allows for possibilities where a main application window View or a highly nested View could listen to messages globally within the application without having direct access to ViewModels in order to attach event handlers and such. To filter out messages that are irrelevant you can look at some sort of message source value or some other indication of where the message originates from. For those comfortable with the idea of Windows Messages and how that works between different controls (Windows) within unmanaged and WinForms development might be a way of understanding a system could be built up on top of a mediator that broadcasts messages.
I prefer to use an action delegate that is inserted via the ViewModel constructor. this also means we can easily verify during unit-testing: