2013-12-14 2 views
5

Я использую инструментарий Galasoft Mvvm Light для создания моего приложения в шаблоне MVVM для телефона Windows. У меня есть страницы, каждая из которых имеет свою собственную модель просмотра.Навигация и повторное создание страниц/конструктор viewmodel

Когда пользователь запускает приложение, он может выбрать новую игру и задать страницу вопросов. Для каждого из них на каждой странице есть viewmodel, и все работает с использованием viewmodellocator. Когда пользователь снова перемещается назад, чтобы снова выбрать новую игру и вопросы. Модель просмотра/страница не удаляется. что означает, что когда пользователь второй раз переходит к вопросам или новой игре, конструктор для viewmodel не вызывается, так что инициализация в конструкторе не запускается, и представление задано неправильно.

Solutions Я попытался

Я попытался удалить backstack в навигаций, таких как новая навигация к новой игре или вопросы, должны раскрутить новую страницу, и тем самым caling конструктор. Не работает.

ИСПОЛЬЗОВАНИЕ загруженного события в представлении и вызов конструктора. Не работает.

Пытался следовать How to reset all instances in IOC Container Но не смог заставить его работать, может быть, только я.

Решите эту проблему, если да, то как ее решить?

Код Здесь вы можете найти пример. Нажмите вопросы и нажмите кнопку там один раз, используйте обратную ссылку. и снова задавайте вопросы. вы видите, что число теперь 1, это можно легко изменить. Но ошибка возникает, когда вы снова нажимаете кнопку. Внезапно отображаются два всплывающих окна.

Итак, как правильно установить режим просмотра. так как представление newgame будет использоваться при перезагрузке старой игры, только с другими значениями, и когда вы захотите начать новую игру. Надеюсь, вы понимаете :)

Этот пример предназначен только для того, чтобы показать мою проблему с подсчетом всплывающих окон для каждого возврата на страницу viewmodel. https://www.dropbox.com/s/gjbz0l8rmsxqzrd/PhoneApp8.rar

ViewModel Локатор Я в моем текущем проекте с использованием трех ViewModels видели в коде ниже:

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 
    } 
} 

Я посмотрел в ссылку я ссылку выше сброса всех экземпляров в контейнер МОК. Но вы не знаете, как работает ключ, и как убедиться, что функция очистки вызывается при навигации вдали от представлений. Так как я не хотел бы очищать все режимы просмотра одновременно.

Navigation И viewmodelbinding

Я связываю свою ViewModel с точки зрения, как

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

Я перемещаться вперед и назад с помощью NavigationService и BackButton.Из меню в игре:

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

и на странице

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

и из игры в меню:

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

И в меню я призываю сборщик мусора. Как видно, я нарушаю структуру MVVM для решения проблемы.

+0

Я думаю, вы получите более конкретные ответы, если вы можете опубликовать конкретный образец, демонстрирующий проблему. Но в целом я считаю, что точка зрения модели состоит в том, чтобы * сохраняться * данные на разных загрузках страниц, поэтому не следует удивляться, что отображение второй страницы сохраняет данные с первого представления. Вы можете справиться с этим, переместив часть инициализации страницы из конструктора в функцию, вызванную из конструктора, а также из загруженного страницы. – BobHy

+0

Это именно то, что я сделал. Но проблема с памятью, так как модель просмотра не очищается при навигации. И поскольку для параметра datacontext установлено представление, я не могу получить доступ к viewmodel позади. То, что я должен был сделать до сих пор, это установить datacontext = null и вызвать GC.collect(). Но это не очень хороший способ сделать это. Я хотел знать, каков правильный путь. – JTIM

+1

Пожалуйста, разместите образец, показывающий, что вы сейчас делаете (с комментариями, показывающими, что вы хотели бы иметь). Наличие модели просмотра V1 для данной страницы P1 все еще остается в памяти, когда P1 загружается второй раз, вот что должно произойти. Вы видите какую-то другую модель представления в P1.DataContext? – BobHy

ответ

3

Свойства вашего ViewModelLocator возвращаются в синглоты. Для того, чтобы свойство возвращать новый экземпляр каждый раз, когда вы могли бы просто написать:

private int questCount; 

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

Однако, это приведет к кеширования Вопрос ViewModel. Вам нужно освободить неиспользуемые ViewModels, внимательно следуя ответу, который вы связали. Это приводит, по моему мнению, к слишком большому коду для простого результата. Существуют и другие контейнеры МОК, которые можно использовать вместо SimpleIoc на Windows Phone (например, ninject или unity), которые могут быть лучше подходят для ваших нужд.

В простом проекте (пара-оф-страниц приложений), особенно в случае отсутствия необходимости большого опыта работы с контейнером МОК, я бы посоветовал вам отказаться от всех, что SimpleIoc электропроводку и просто вызовите конструктор:

public Question Quest 
{ 
    get { return new Question(); } 
} 
+0

Спасибо за ваш ответ, мой проект довольно большой, и я использую три модели просмотра. Я попытался реализовать функцию очистки, не заставляя ее работать, поскольку я не знал, как вызывать очистку, и как обеспечить, чтобы очистка была сделана для всех переменных, даже если они являются статическими. Я могу сделать код, с которым я связался, и заставить его работать, но я не понимаю, как работает ключ. Поэтому я не очень люблю использовать код, я не знаю, как его поддерживать. Поэтому я хотел бы использовать SimpleIoc, поскольку я использую свет MVVM, но не знаю, как это сделать. Я обновлю свой вопрос с помощью своего Viewmodellocator. – JTIM

+0

@JTIM Три модели ViewModels с очень простыми конструкторами (судя по вашей настройке SimpleIoc) - это * определенно * случай, когда я бы * не * использовал контейнер IOC. Явные вызовы конструктора дают гораздо меньше кода, который вы определенно понимаете. – lisp

+0

@JTIM Что касается SimpleIoc - GetInstance возвращает тот же экземпляр, GetInstance с заданным ключом дает тот же экземпляр для данного ключа. Unregister позволяет удалить экземпляр, назначенный ключу. Это просто спецификация SimpleIoc. Это делает его полезным в некоторых сценариях, в некоторых из них трудно применять. SimpleIoc - это всего лишь один из помощников MVVMLight - вам не нужно использовать их в каждом проекте. ViewModelLocator можно легко написать без него. – lisp

Смежные вопросы