3

I'm developing a WPF based MVVM application and have a question relating to the best way of approaching view navigation within my application. Specifically, I am interested in the cleanest way to approach this navigation when I have multiple views that can cause navigation.

Let me summarize my current application layout so that I can better explain the problem.

The diagram above shows the rough layout of my main shell. The Main Navigation area is static and provides a number of buttons. Buttons exists for primary application functions such as Status, Configuration, Diagnostics etc. When one of these buttons is pressed, the content of the Contextual Navigation area is set. Specifically, this achieved by having the contextual navigation area contain a content control with the Content property bound to a single property of type ViewModelBase. In addition, the view models and views are tied together with data templates in the application resources.

The specific view/viewmodel populated in the contextual navigation content control then provides addition navigation options that are relevant to the primary function selected in the main navigation. When an option is selected in the contextual navigation, the main content region is updated in exactly the same way as described with the contextual navigation previously.

So I suppose you could describe the combination of MainNavigation and ContextualNavigation areas something very similar to an Outlook Style menu bar. i.e. primary selection at the bottom, secondary selection at the top, resulting in a change in main content area.

Now to the problem. I can make this work, but it's starting to get very messy! I've got the MainNavigationViewModel causing navigation, and multiple contextual ViewModels that get populated in to the ContextualNavigation area causing navigation. On some occasions, it may be that an action in the main content area also creates the need for navigation also. I've also actually got a Ribbon control that may also cause some navigation. So I've got navigation everywhere spread throughout my ViewModels and I don't believe that it is maintainable. PS. In case you were wondering, I'm currently using a messenger system to allow decoupled communication between view models.

I'm starting to think the best approach is to create an abstract service that takes care of navigation for all the view models within my application but not sure what that would look like. Am I on the right lines here and if so, does anyone have any suggestions for an application wide navigation service that handles navigations from multiple view models?

Sinatr
  • 20,892
  • 15
  • 90
  • 319
Lee
  • 71
  • 1
  • 2
  • IMHO. As a user it is confusing me the way that Main and Contextual Navigation are structured. I would propose to use just a ribbon as Office and Windows 10 does – Athafoud Jan 15 '16 at 12:11
  • Maintain 2 lists of ViewModels for each navigation (main and contextual one). Visualize those lists as some controls (e.g. list of Buttons), clicking either will make that ViewModel active and it will get displayed as content. Each ViewModel should have access to navigation features `INavigate` (e.g. `INavigate.AddContextTarget()` - add something in contextual navigation), you can provide access to it via constructor parameter. – Sinatr Jan 15 '16 at 12:14
  • I would suggest using the former Microsoft's Prism MVVM (now community maintained) Framework for that, it offers a region manager and navigation service for exactly this situation. https://github.com/PrismLibrary – Tseng Jan 15 '16 at 12:39

1 Answers1

0

first of all what MVVM approaches are you using? View first or View Model first?

the right choice can make you life easier.

The idea you already have go's into the right direction Interfaces and inheritance - abstracting the navigation layer.

if you already use Messanger it's actually follows a similar approaches. in your case an architecture plan would be more than necessary, take yourself time and draw it down.

Oscar
  • 53
  • 6
  • Imho navigation via messages/events is kinda painful, you can't react on user interactions or cancel navigation when let's say the currently active viewmodel has modified data and has to ask user whether he wants to save/discard the changes or chancel the navigation attempt in order to do another change and commit it. This works very well with a navigation service and ViewModels that implement `INavigationAware` interface (i.e. PrismLibrary), where a viewmodel can cancel a navigation attempt when certain conditions are met or are not met – Tseng Jan 15 '16 at 12:43