Question

I am using Galasoft Mvvm Light toolkit, to build my application in the MVVM pattern for windows phone. I have to pages that each have their own viewmodel.

When a user starts the app he can choose new game og spin up a questions page. These to pages have each a viewmodel, and everything works using the viewmodellocator. When the user then navigates back to choose between new game and questions again. The viewmodel/page is not removed. which means when the user a second time goes into questions or new game, the constructor for the viewmodel is not called, such that the initialisation in the constructor is not run, and the view is not set correctly.

Solutions I have tried

I tried removing the backstack in the navigations, such as a new navigation to new game or questions, should spin up a new page, and thereby caling the constructor. Not working.

USing the loaded event in the view, and calling the constructor. Not working.

Tried to follow How to reset all instances in IOC Container But could not get it to work, might just be me.

Have anyone solve this issue, if so how should it be solved?

Code Here you can find an example. Press questions, and press the button in there once, use backkey. and press questions again. you see that the number is now 1, this could easily be changed. But the error comes when you press the button again. Suddenly two popups are shown.

So what is the correct way to set up the viewmodel. since the view of newgame will be used when reloading an old game, just with other values, and when one wants to start a new game. Hope you understand :)

This example is only to show my problem with popups count going up for each return to the viewmodel page. https://www.dropbox.com/s/gjbz0l8rmsxqzrd/PhoneApp8.rar

ViewModel Locator I am in my current project using three viewmodels seen in the below code:

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;

namespace MVVMTestApp.ViewModel
{
public class ViewModelLocator
{
    public ViewModelLocator()
    {
        //Holder styr på ViewModels
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        //Tilføj linje her for hver ViewModel
        SimpleIoc.Default.Register<MainViewModel>();
        SimpleIoc.Default.Register<MainViewModelTest>();
        SimpleIoc.Default.Register<MenuViewModel>();
    }

    //Tilføj metode som denne for hver ViewModel
    public MainViewModel Map
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }

    public MainViewModelTest Main
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModelTest>();
        }
    }

    public MenuViewModel Menu
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MenuViewModel>();
        }
    }

    public static void Cleanup()
    {
            // TODO Clear the ViewModels
    }
}

I have looked into the link I reference above resetting all instances in IOC Container. But are unsure how the key works, and how to make sure the cleanup function is called when navigating away from the views. Since I would not want to clean all the viewmodels at the same time.

Navigation And viewmodelbinding

I bind my viewmodel to the view as

DataContext="{Binding Source={StaticResource Locator},Path=Map}"

I navigate back and forth using NavigationService and backbutton. From Menu to Game:

NavigationService.Navigate(new Uri("/View/MainPage.xaml", UriKind.Relative));

and in the page

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        //e.Content = NavigationMode.New;
        //e.NavigationMode = NavigationMode(
        ViewModel.MainViewModel test = new ViewModel.MainViewModel();
        GC.Collect();
        base.OnNavigatedTo(e);
    }

and from Game to Menu:

protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        //e.NavigationMode = NavigationMode.
        this.DataContext = null;
        GC.Collect();
        base.OnNavigatedFrom(e);
        //test = null;
    }

And in the menu I invoke the garbage collector. As can be seen I break the MVVM structure to accommodate the problem.

Was it helpful?

Solution

Properties of your ViewModelLocator return Singletons. To make the property return a new instance each time you could simply write:

private int questCount;

public Question Quest
{
    get
    {
        return ServiceLocator.Current.GetInstance<Question>((++questCount).ToString());
    }
}

However, it will result in Question ViewModel caching. You need to release unused ViewModels by closely following the answer you linked. This results in my opinion in too much code for a simple result. There are other IOC Containers that you could use in place of SimpleIoc on Windows Phone (like ninject or unity), which may be better suited for your needs.

In a simple project (a couple-of-pages app), especially in the case of not having to much experience with IOC container, I would advise you to abandon all that SimpleIoc wiring and just call the constructor:

public Question Quest
{
    get { return new Question(); }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top