1

I really made a search for this topic and did not find anything, and because of that, I am asking the question here.
I have a WPF application with Prism installed.
I have wired the view-model with the view automatically by name convention

<UserControl x:Class="Views.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">

and the model in the 'Model' like this

public class ViewAViewModel {
    public ViewAViewModel () {
         // time-resource consuming operations
    }
}

the automatic binding work perfectly without a problem and the view and its corresponding view-model is matching, but the problem here. I have a lot of those views say (50) and for every one of them, the view-model will be created with constructor exhausting the processes. This will make the startup of the application longer and also it will create a lot of view-models objects and put them in the RAM without being sure that they will be used at all.

What I need is to create the view-model class when the view is activated (I mean when the view is navigated to). Is this possible and if yes how?

Update

here is how I register the view with the Module, this is causing all the views to be created when the startup of the module.

public class Module1 : IModule
{
    public void OnInitialized(IContainerProvider containerProvider)
    {
        var regionManager = containerProvider.Resolve<IRegionManager>();

        regionManager.RegisterViewWithRegion("region1", typeof(View1));
        regionManager.RegisterViewWithRegion("region1", typeof(View2));

is there any way to delay the creating of the views, until the navigation request come?

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
  • Use a [NavigationService](https://github.com/microsoft/BikeSharing360_MobileApps/blob/master/src/BikeSharing.Clients.Core/Services/NavigationService.cs) that can also solve your time-consuming constructors. Have a look at VM InitializeAsync method – Sir Rufo Jun 02 '19 at 07:07
  • What does `for every one of them, the view-model will be created with constructor exhausting the processes` mean? View models will be created when the view is created, why do you create 50 views at start-up? – Haukinger Jun 02 '19 at 11:42
  • @Haukinger this is really interesting, thank you for let me notice this fact. your comment really shifts my mind to another way of thinking. Maybe a better way to restrict the constructing of the views. Now, all the views are created when the Main application startup, can you provide me any hint about delaying the creation of the views ? – Hakan Fıstık Jun 02 '19 at 12:42
  • @Haukinger Please see the update on the question – Hakan Fıstık Jun 02 '19 at 12:53
  • 1
    Creating a view is typically way more expensive that viewmodel. I recommend to move all I/O and CPU expensive operations out of the viewmodel's ctor to a method that will be called when view is loaded. That way you don't need to bother with viewmodel lazy instanciating. Besides, having a view without viewmodel is kind of weird in MVVM and can cause issues in future – Liero Jun 02 '19 at 13:08
  • @Liero thanks for the advice, I really went this way. Post your comment as an answer and I will accept it and upvote it. – Hakan Fıstık Jun 02 '19 at 15:11

1 Answers1

1

You could use navigation, for each view. Or you must create an interfaces for your view and view model. An example:

public interface IMyView
{
    IMyViewModel ViewModel { get; set; }
}
public interface IMyViewModel
{

}

In the module or app.cs, in the method RegisterTypes you should register these.

containerRegistry.Register<IMyView, MyView>();
containerRegistry.Register<IMyViewModel, MyViewModel>();

You must implement IMyView interface in your MyView.cs class.

public partial class MyView : UserControl, IMyView
{
    public MyView(IMyViewModel viewModel)
    {
        InitializeComponent();

        ViewModel = viewModel;
    }

    public IMyViewModel ViewModel 
    {
        get => DataContext as IMyViewModel;
        set => DataContext = value;
    }
}

After you could use it:

public void OnInitialized(IContainerProvider containerProvider)
{
    var regionManager = containerProvider.Resolve<IRegionManager>();

    var firstView = containerProvider.Resolve<IMyView>();

    regionManager.AddToRegion(RegionNames.MainRegion, firstView);
}

In such case you shouldn't use ViewModelLocator.AutoWireViewModel in your view.

Noisy88
  • 181
  • 1
  • 14