I am looking for an little example of wpf project where contains a best practice to navigate between views. Maybe with the framework MVVM Light and a NavigationService or ServiceLocator. Instead of calling View from ViewModel, how do you do that? How is your approach? Do you have a project example?
2 Answers
I prefer ViewModel first approach. That means navigation service take viewmodel as a parameter and then, based on naming convention, instance of view is created and loaded into frame.
navigationService.Navigate<SomePageViewModel>()
This has couple of advantages over URI based navigation, which is view first approach:
- Better testability
- possibility of dependency injection into view
- most important: Better maintability. If you rename or move your pages, this will won't compile until you fix it, unlike URIs. Uri's would throw error at runtime
Unfortunelly, I can't give you mine example project right now, but it's quite easy to implement your own

- 25,216
- 29
- 151
- 297
-
What if you have an applications with tabs.every click on the MenuItem should open a Windows with a ViewModel.How do you do that? – MrScf Mar 07 '15 at 21:34
-
1In that case, navigation service is not suitable, because its not navigation based app :) You need MainWindowViewModel with Tabs and SelectedTab properties. They can be of type type TabViewModelBase. Each tab will be represented by concrete VM class. To open new tab, you just add instance of TabVM to Tabs in your MainWindowVM. In MainWindow you have TabControl with ItemsSource bound to Tabs and DataTemplateSelector – Liero Mar 08 '15 at 07:23
-
1Ok, maybe I misunderstood your comment. What I have described is tab based UI, like Visual Studio for example. If you want to open new window (dialog) you should use another service class, e.g. DialogService, because it's completelly different behaviour than navigating between pages – Liero Mar 08 '15 at 07:44
A way I favour is to have a main window with a content control. Behind that is a view model with an application state property based upon a shared enumeration.
The enumeration is intended to represent the current state but consider each to be the view you want displaying if that's easier.
Using a template selector bound to this property I control the view presented within the content control on my main window.
This approach requires you to manage a template selector with template properties for each enumeration value or view you want to be the main content. But the template only needs to include an instance of your view, so minimum XAML.
In the background, I use MVVM light to provide a Viewmodel locator data source making my views really easy to instantiate. They also use a singleton viewmodel so state is managed in between uses. I then also use the messaging framework to send messages to my main window view model telling it which state I now want. This means any viewmodel can post a message to switch to another state, without knowing what view that will be, but ultimately the main window view model manages that transition.
Apologies for lack of code examples here, this is an outline of something I have done a number of times but I don't have a clean sample to share.
This is hopefully enough to explain my approach, but feel free to comment if this doesn't make sense or fit what you're trying to do.
For dialogs... Typically I have default dialogs I reuse, but the same principle can be used. Instead of being the main window control and VM, have a secondary one for dialogs which works the same but makes itself visible as requested and closes itself once complete. Again mvvm light messenger is your friend here.
Your message includes the dialog 'state' which controls the view presented.
This would only work if your design will allow only one dialog at a time.
Finally, for tabs...
I'd look at having an observable collection of the state enumeration in the main view model. Then build the tabs by binding to that. Not something I've done but that is where I'd start. –

- 3,423
- 2
- 16
- 28
-
Thanks kidshaw! Your approach sounds really well but I wonder,what if you want to show a View as a Dialog. Where and how do you solve this topic? And when you say, the current state...that is an enum with the name of the View to show..? Thanks a lot for your comment again – MrScf Mar 07 '15 at 20:37
-
It's simple. If you want to navigate to another page use NavigationService. If you want to show Dialog, create and use DialogService. – Liero Mar 08 '15 at 07:26
-
-
My response seems to have dropped somewhere. @Liero - this is an alternative strategy to yours, not to say yours isn't correct - this is just an alternative. – kidshaw Mar 08 '15 at 07:30
-
-
@kidshaw: wouldn't it be better to use DataTemplateSelector for your views based on naming convention rather then to maintain it each time you create new view? – Liero Mar 08 '15 at 07:36
-
I prefer not to. I'd sooner not build in a convention to the code as it can easily be forgotten and is tricky to debug. Basing it on an enumeration means I can also reuse templates across more than one value giving me a point in code where I make a controlled decision. It works better for forgetful developers like me :) – kidshaw Mar 08 '15 at 07:40
-
1. ‘forgetting’: You can easily create test for your convention, foreach vm there must be corresponding view. And you will never forget, because tests will remind you. Btw, you can forget to maintain your template selector as well. 2. ‘debugging’ your template selector should throw you exception with descriptive message like "Navigation Page1ViewModel failed. Page1.xaml cannot be found. You won't need to debug it then. 3. ‘reusing’: I dont get it – Liero Mar 08 '15 at 07:55
-
Valid points, the reuse comes from being able to manage more than one state to the same template. The state becomes more general than just controlling which view - the view itself can make changes internally for different states. – kidshaw Mar 08 '15 at 08:05