3

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,

Community
  • 1
  • 1
David Gutierrez
  • 383
  • 4
  • 13
  • 1
    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 Oct 12 '12 at 19:47
  • Than what are the navigation facilities of the second answer I referenced exactly for? – David Gutierrez Oct 15 '12 at 13:49
  • 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 Oct 15 '12 at 13:58
  • I see, thanks for the information. Another question if you don't mind: How do you handle transition effects with your method? – David Gutierrez Oct 15 '12 at 14:07
  • 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 Oct 15 '12 at 14:10
  • I see, I guess I was hoping for a built in way to accomplish this. Another question (if you don't mind, thanks again for the help): Where do you house your data templates so that you can edit and see them within Visual Studio at design time? Currently Visual studio won't render my data templates when they're within a resource dictionary. – David Gutierrez Oct 15 '12 at 14:57

2 Answers2

1

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>     
eran otzap
  • 12,293
  • 20
  • 84
  • 139
  • Thanks, I already had this implemented as per the first answer I linked to. I'm wondering why this is preferred over the second answer, and which is the correct way to go. – David Gutierrez Oct 15 '12 at 13:49
  • well on MVVM Light toolkit you use a 3rd party library wich isn't part of the wpf framework , i think implementing on top of the framework is of more benefit since you can maintain your own code and also you get a clearer picture of how the framework works . – eran otzap Oct 15 '12 at 17:27
1

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.

David Gutierrez
  • 383
  • 4
  • 13