Navigation should always be handled in the ViewModel.
You're on the right track with thinking that the perfect implementation of the MVVM design pattern would mean you could run your application entirely without Views, and you can't do that if your Views control your Navigation.
I usually have an ApplicationViewModel
, or ShellViewModel
, which handles the overall state of my application. This includes the CurrentPage
(which is a ViewModel) and the code for handling ChangePageEvents
. (It's often also used for other application-wide objects such as the CurrentUser, or ErrorMessages too)
So if any ViewModel, anywhere, broadcasts a ChangePageEvent(new SomePageViewModel)
, the ShellViewModel
will pickup that message and switch the CurrentPage
to whatever page was specified in the message.
I actually wrote a blog post about Navigation with MVVM if you're interested
I guess it depends. On the project I am currently working on, we have used both approaches. I suppose it comes down to how related the child window's functionality is to the parent. If the new window is mostly supplemental, such as a prompt or minor input dialog, I have simply used the parent's data context because the data being provided through that dialog was still very relevant to the parent's functionality. On the other hand, if the new window is a significant feature in itself, it may be more appropriate to use a new data context that reports back to the parent (if applicable). Think of it this way, when designing a class, when is it appropriate to break out functionality into another class? You don't necessarily want an unwieldy view-model with a bunch of unrelated functionality lumped together.
Unfortunately, this has turned into a pretty fuzzy answer that depends on your best judgment.
Best Answer
Your model classes should be simple and only store the data you wish to model for your application. You should avoid having any complicated methods or business logic in your model classes. I usually have constructors and basic properties (i.e. public getters, private setters) in my model classes and that tends to suffice.
Your view model classes should contain business logic and anything else required to facilitate presenting the data in your model classes in the corresponding views. View model classes can also access other required dependencies, such as environment variables. If you find that several view model classes require access to environment variables, you may want to introduce a separate class that accesses environment variables and then include this class as a dependency in your view model classes, preferably using dependency injection.