Best place to create a ViewModel in MVVM [closed]
Asked Answered
D

3

7

I have a question: Where is the best place to create the ViewModel in MVVM and how?

1) Create once in App.xaml.cs as static field and then use it through App?

2) Alway create new ViewModel in Page.cs, when I navigate to this page?

3) other options

Dessertspoon answered 19/9, 2012 at 18:45 Comment(1)
I've always seen it part and parcel with the view creation.Swiger
C
11

In MVVM, the ViewModel is the application. This means that I usually have an single startup ViewModel that is the entry point to my application, and I typically create an instance of this in the App.xaml.cs OnStartup code

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    var app = new ShellView();
    var context = new ShellViewModel();
    app.DataContext = context;
    app.Show();
}

Every once in a while I have an application that will create the ViewModel in the startup window's constructor, but this is not really preferred because it means if I have any startup logic, I have to put that in the code-behind the View as well, and I don't like mixing application logic in my View layer.

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ShellViewModel();
    }
}

Regardless of how you do it, keep in mind that when using MVVM, your ViewModels are your application, not your Views, so typically your ViewModels are connected in some way to the startup ViewModel. Views are just a user-friendly way for users to interact with your application (the ViewModels).

Clotilda answered 19/9, 2012 at 19:14 Comment(3)
How does this work when there are many views with different ViewModels? Does your OnStartup method set all the DataContexts? What happens when new Views are created?Collinsia
Hi Adrian, usually I only hook up the main ShellView and ShellViewModel like this. I tell WPF how to draw the rest of the ViewModels by placing an implicit DataTemplate in the .Resources of the application somewhere. When WPF goes to draw a ViewModel, it will check to see if there is a DataTemplate it should use to draw that ViewModel, and use it if so.Clotilda
Thanks for that Rachel. I need help from my colleague to unpack it because I had imagined DataTemplates were only usef with ItemsControls.Collinsia
P
2

There are different ways to do it, depends on what you think.

I personally always have a class designed to create all the objects I need, called in the App.xaml.cs. The class basically does those time-consuming startup procedures while a splashscreen is displayed. I create both Views and ViewModels here AND link them

This allows me to have one and only one point in which all those links View-to-ViewModel are created, I can come back to it easily, even if I add/remove something.

I don't like the approach in which you initialize the viewModel in each view's constructor. Assuming you have 15 views in your project, you'd have 15 different files to browse if you want to check all the ViewModel initializations.

This is my humble participation to this =)

Perren answered 19/9, 2012 at 19:2 Comment(0)
T
1

You can use dependency injection and create it like this (assuming you're using some DI container):

 public partial class YourView : UserControl
{
    public YourView (IYourViewModel viewModel)
    {
        InitializeComponent();
        this.DataContext = viewModel;
    }
}
Transcurrent answered 19/9, 2012 at 18:55 Comment(5)
That's what I'd do as well. However assuming you need to show another UserControl or a Dialog from YourView, how would you supply them with their ViewModel without passing your DI container around as well?Tailorbird
They could be injected into their constructors, as long as the container has them registered. Another option maybe to have YourView pass something or set a property on the others?Transcurrent
True, but injecting Views into ViewModels would create the dependency to the presentation layer I try to avoid. How about raising some kind of event in the ViewModel and let some outside instance - a controller maybe - create and show the View that needs to be shown?Tailorbird
I don't mean injecting a view into a viewmodel. As for events, I think you can raise an event, maybe with a viewmodel as payload, and load the usercontrol from that.Transcurrent
Ah sorry, I got you wrong then. Did you mean injecting the the View that should be opened by YourView via YourView's constructor?Tailorbird

© 2022 - 2024 — McMap. All rights reserved.