3
votes

I'm new to using WPF, and I'd like to see what people recommend as best practice when it comes to navigating across multiple screens in a WPF application that is using the MVVM Light Toolkit. Being new to WPF, please excuse me if my terminology is incorrect as I'm not sure if the proper term is "switching views", "navigating pages", "changing windows", or something else (clarification on these terms as related to WPF would be appreciated).

To clarify what I want to do: I have an application that has 3 full screen pages/views the user should be able to move back and forth from. These views will never be displayed at the same time, so they're most easily compared to tabs in a tab control; except I don't want the tab strip that a tab control usually comes with. Instead I'd like to switch between pages/views programmatically.

I've seen a couple different approaches, in the following stack over flow answers:

  1. https://stackoverflow.com/a/6114865/1081879
  2. How to navigate through windows with MVVM Light for WPF?

So really I am just wondering which of the above to approaches is the direction I should head in? I've already actually implemented the first answer, but I'm not sure if doing this is an "abuse"/"hack" of data templates or if this is how the framework should be used.

Finally, perhaps MVVM Light isn't the most suited toolkit I could be using if other toolkits provide this functionality out of the box. Could anyone shed light on this notion, and maybe recommend a more suited toolkit?

Thanks,

2
That's actually exactly how WPF is supposed to work :) Your application consists of the objects you create (ViewModels/Models), and you use DataTemplates and UI objects to tell WPF how to draw your application. That's the opposite of WinForms where you build your application out of UI objects, and supply them with the data needed. - Rachel
Than what are the navigation facilities of the second answer I referenced exactly for? - David Gutierrez
I haven't used that code before, but it appears to be a framework that accomplishes the same thing. You set the an object to be the "Current" page, and it uses a ViewModelLocator to locate the correct View to draw the page with. - Rachel
I see, thanks for the information. Another question if you don't mind: How do you handle transition effects with your method? - David Gutierrez
I would handle them from the View since they are a View-Specific function. I'd probably attach something in the code-behind that listens for changes, and run some animation when one occurs. The simplest way would probably be to subscribe to the PropertyChange event of the ViewModel, although I'm sure there's other ways to do that as well, such as using a messaging system. - Rachel

2 Answers

1
votes

a quick and dirty example of navigation (this was written here and not in VS so if something is misspelled please apply a the fix ) :

lets create an hierarchic description of our views :

  public abstract Class ViewModelBase : INotifyPropertyChanged{} 
  public abstract Class ViewModelNavigationBase : ViewModelBase {} 
  public Class ViewModel1 : ViewModelNavigationBase {}
  public Class ViewModel2 : ViewModelNavigationBase {}
  public Class ViewModel3 : ViewModelNavigationBase {}

  public Class MainViewModel : ViewModelBase 
  {
      private ViewModelNavigationBase  currentViewModel; 
      public ViewModelNavigationBase  CurrentViewModel 
      {
         get{return currentViewModel;}
         set
         {
            currentViewModel = value;
            OnPropertyChanged("CurrentViewModel");                
         }
      }          

      private const int numberOfPages = 3 ;
      private int index;
      private ViewModelNavigationBase[numberOfPages] pages;
      ....
      ... OnNavigateCommand()
      {
          index++;
          index = index % numberOfPages;
          CurrentViewModel = pages[index];
      }

 }

resources :

     <local:MainViewModel x:Key="MainVm" /> 

     <DataTemplate TargetType={x:Type local:ViewModel1}>
         <local:View1 />
     </DataTemplate>

     <DataTemplate TargetType={x:Type local:ViewModel2}>
         <local:View2 />
     </DataTemplate>

     <DataTemplate TargetType={x:Type local:ViewModel3}>
         <local:View3 />
     </DataTemplate>

xaml :

 <Window x:Name="MainWindow" 
         DataContext={StaticResource MainVm}>
       <StackPanel>
           <ContentControl Content={Binding CurrentViewModel} />
           <Button Content="Navigate" Command="{Binding NavigateCommand}"/>
       </StackPanel>       
 </Window>     
1
votes

What I really was looking for in the question was a reference that showed one of the two approaches I listed was actually commonly used and a solid approach.

I've finally stumbled onto this: http://msdn.microsoft.com/en-us/library/gg405484%28v=PandP.40%29.aspx

Which calls out the first way of using data templates for your view models.