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
Normally I have one overarching ApplicationViewModel
that takes care of initializing ViewModels for separate screens, like this, however because of the nature of your application, it sounds like your CompanyOverviewScreenViewModel
should work fine for this purpose.
Typically I would have is my main application initialize the top-level data context, and each ViewModel from there is in charge of creating/maintaining viewmodels below it.
For example :
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainApp = new CompanyOverviewWindow();
var appData = new CompanyOverviewScreenViewModel();
mainApp.DataContext = appData;
mainApp.Show();
}
}
The CompanyOverviewScreenViewModel
would contain a collection of CompanyModel
objects, and upon selection each CompanyModel
object would be displayed to the user in some kind of ContentControl
or UserControl
. Each CompanyModel
would further have a collection of EmployeeModel
objects that could also be selected and displayed.
Keep in mind that a ViewModel
is really just a model of the View. For example, it sounds like you only want to display Employee objects, so using the EmployeeModel
directly is perfectly acceptable. But if you wanted to provide the ability to update the EmployeeModel
and include items like Save, Cancel, Delete, etc you would probably want a ViewModel
to contain the extra code that is unrelated to the Employee data object itself.
In that same vein, because you want to do things like track the Selected Employee of each CompanyModel
, something not normally part of the Company data object, it might make sense to use a CompanyViewModel
object at that layer too. Sometimes for something as simple as just tracking selection though, I'll just add it the object model. It really depends on how big or how structured the application is.
Overall what you have now looks like you're going in the right direction, although I did have some concern about your image where it says "Each screen creates ViewModels.." in the top left corner. I typically do not advocate for a view-first approach to MVVM and WPF, and would recommend a ViewModel-first approach instead, as I described here.
Best Answer
It's really hard to say where do you draw the line between single and shared ViewModel usages.
As a rule of thumb, I would use shared ViewModel in the case and only in the case when two or more views create an inseparable logical unit, but because of the screen size, they are separated in multiple views.
For example, if you create some very long object, with lots of data, and this data doesn't fit nicely into one screen so you need two screens. This very long object needs data from both screens or it should not be created. In this case, if you have a shared view model it will save you from the headache of drafting inconsistent data in your local storage or transferring large parcellable objects.