0

Suppose I have a window called MainWindow.

Inside that I have a Menu and a Frame, which is used to display a page associated with SelectedMenuItem.

Suppose I have 10 pages named Page1, Page2, ......, Page10. Now I would like to display those pages in Frame. All the pages has got some standard controls like TextBox, TextBlock, ComboBox etc.

Functionality :

  1. User Clicks on any MenuItem and a page associated with that MenuItem Is displayed to him.
  2. He will fill all the TextBoxes and ComboBoxes with data as per his needs.
  3. He will click on Save Button (Please note that save Button is located on MainWindow and not on any Page.)
  4. Steps 1,2,3 continues till user's wish.

Now, my questions are :

  1. Should I use a ViewModel per Page?
  2. Should I use only 1 ViewModel?
  3. What are the advantages and dis-advantages of using a Single ViewModel?
  4. What are the advantages and dis-advantages of using a Multiple ViewModels?
  5. If you say that I should use Multiple ViewModels, then how should I refer to properties of one ViewModel in another ViewModel?

Please don't say that it depends on the programmer's mind. I have asked these questions because I want to create a small Data-entry application. And I would like it to be maintainable. Also, I would like to create the application in best way possible.

Vishal
  • 6,238
  • 10
  • 82
  • 158
  • 1
    1. We always did one viewmodel per page. Just so you dont have to account for other pages classes. 5. We would make classes and put them in a view model so if you wanted one class in both you would just add it to each one instead of the individual properties – Ryan Schlueter Mar 20 '14 at 18:03
  • I can't understand 5. in your comment. – Vishal Mar 20 '14 at 18:11

2 Answers2

2

This is primarily opinion based.

Still, my opinion is that you need a MainViewModel which has an ObservableCollection<PageViewModel> where each is associated with a proper DataTemplate (containing the Page UI) and an ActivePage property to which a ContentPresenter's content is bound:

public class MainViewModel
{
    ObservableCollection<PageViewModelBase> Pages {get;set;}

    PageViewModelBase ActivePage {get;set;}
}

public class PageViewModelBase
{
   //.. logic common to all pages
}

public class PageViewModel1: PageViewModelBase
{
   //.. logic which belongs to Page 1
}

public class PageViewModel2: PageViewModelBase
{
   //.. logic which belongs to Page 2
}

//And so on...

XAML:

<Window ...>
    <Window.Resources>
       <DataTemplate DataType="{x:Type local:PageViewModel1}">
           <local:Page1/>
       </DataTemplate>

       <DataTemplate DataType="{x:Type local:PageViewModel2}">
           <local:Page2/>
       </DataTemplate>

       <!-- and so on... -->
   </Window.Resources>

   <ContentPresenter Content="{Binding ActivePage}"/>
</Window>

WPF's Implicit DataTemplate capabilities will take care of rendering the appropiate DataTemplate when the ActivePage is changed.

Edit:

There are several ways to deal with ViewModel-to-ViewModel communication.

Direct reference

ViewModel1 holds a reference to ViewModel2 and manipulates it as needed:

public class ViewModel1
{
    public ViewModel2 ViewModel2 {get;set;}

    void SomeMethod()
    {
        ViewModel2.SomeProperty = "SomeValue";     
        ViewModel2.ExecuteSomeAction(someParameter);
    }
}

EventAggregator / Messenger pattern:

see This Answer

Community
  • 1
  • 1
Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
  • Thanks, a Good One. Can you also answer question no 5? – Vishal Mar 20 '14 at 18:19
  • "This is primarily opinion based." Then maybe you should vote to close? – N_A Mar 20 '14 at 18:38
  • Thanks for the great effort. Sorry, it was my mistake in asking a good question. I think I need more explanation on question no 5. Suppose I have a property called MyProperty in MainViewModel. Now I want to get its value in PageViewModel1. How can I get it? – Vishal Mar 20 '14 at 18:44
  • @HighCore I have tried `Direct Reference` method. But ViewModel2 is always null and it makes sense. How can I initialize ViewModel2 property defined in ViewModel1 Class? – Vishal Mar 22 '14 at 19:46
1

In your place, I would use a DataTemplate for each View, because DataTemplate allows to create very dynamic applications.

Should I use a ViewModel per Page?

If the logic of each page is very different from each other, then yes - you need to use a separate View/ViewModel for each page.

What are the advantages and dis-advantages of using a Multiple ViewModels?

The main advantage - it's single responsibility principle SRP:

a class should have only a single responsibility

In our situation, class - View/ViewModel. This object has only one task, and it is independent over the others. For example, you have a task to print page and show the table. Both tasks are unrelated, appropriately it should be implemented in different software entities. This is done in order to independently change the logic of each class.

Disadvantage: for each page will have to do a separate View/ViewModel, that can be a bit time consuming and resources.

Should I use only 1 ViewModel?

In this situation, there will be one base ViewModel, which should contain the basic logic of all its descendants.

What are the advantages and dis-advantages of using a Single ViewModel?

Advantage: will be only one base ViewModel can only inherit her and complement functional. Conclusion: it is easier to use.

Disadvantage: Not always and not everywhere you can find the right base class. If one define it wrong logic, it would be a problem in the further development of the application, because all descendants will inherit from him.

If you say that I should use Multiple ViewModels, then how should I refer to properties of one ViewModel in another ViewModel?

There are several ways, I like most about the Mediator pattern:

The mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program's running behavior.

Here, you can see example of using this pattern.

Also advise you to look at examples of work with DataTemplate in the style of MVVM:

Resolving windows in Structure Map or how to manage multiple windows in WPF MVVM?

Make (create) reusable dynamic Views

Community
  • 1
  • 1
Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68