2013-12-14 8 views
5

Sto utilizzando il toolkit Galasoft Mvvm Light, per creare la mia applicazione nel modello MVVM per Windows Phone. Devo pagine che ognuna ha il proprio modello visivo.Navigazione e reinstanciate pagine/viewmodel costruttore

Quando un utente avvia l'app, può scegliere un nuovo gioco o creare una pagina di domande. Queste pagine hanno ciascuna un modello di visualizzazione e tutto funziona utilizzando il viewmodellocator. Quando l'utente torna indietro, sceglie di nuovo tra il nuovo gioco e le domande. Il viewmodel/pagina non viene rimosso. il che significa che quando l'utente passa una seconda volta in domande o in un nuovo gioco, il costruttore del viewmodel non viene chiamato, in modo tale che l'inizializzazione nel costruttore non venga eseguita e la vista non sia impostata correttamente.

Solutions Ho cercato

Ho provato a rimuovere il backstack nelle navigazioni, come ad esempio una nuova navigazione a nuova partita o domande, dovrebbe girare su una nuova pagina, e caling quindi il costruttore. Non funziona.

Utilizzo dell'evento caricato nella vista e chiamata al costruttore. Non funziona.

cercato di seguire How to reset all instances in IOC Container ma non riusciva a farlo funzionare, potrebbe essere solo me.

Qualcuno ha risolto questo problema, in caso affermativo come dovrebbe essere risolto?

Codice Qui puoi trovare un esempio. Premi le domande e premi il pulsante una volta, usa il tasto indietro. e premere di nuovo le domande. vedete che il numero ora è 1, questo potrebbe facilmente essere cambiato. Ma l'errore arriva quando si preme di nuovo il pulsante. All'improvviso vengono visualizzati due popup.

Quindi qual è il modo corretto di configurare il modello di visualizzazione. poiché la vista di newgame verrà utilizzata quando si ricarica un vecchio gioco, solo con altri valori, e quando si vuole iniziare un nuovo gioco. Spero che tu capisca :)

Questo esempio è solo per mostrare il mio problema con il conteggio dei popup che sale per ogni ritorno alla pagina viewmodel. https://www.dropbox.com/s/gjbz0l8rmsxqzrd/PhoneApp8.rar

ViewModel Locator io sono nel mio progetto attuale utilizzando tre ViewModels visto nel seguente codice:

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

Ho esaminato il link mi riferisco soprattutto il ripristino di tutte le istanze di CIO Container. Ma non sono sicuro di come funzioni la chiave e come assicurarsi che la funzione di pulizia venga richiamata quando si naviga lontano dalle viste. Dal momento che non vorrei pulire tutti i viewmodels allo stesso tempo.

Navigazione E viewmodelbinding

mi legano il mio ViewModel per la vista come

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

a navigare avanti e indietro utilizzando NavigationService e BackButton.Dal menu a Gioco:

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

e nella pagina

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

e da gioco a Menu:

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

e nel menu invoco il garbage collector. Come si può vedere, interrompo la struttura MVVM per far fronte al problema.

+0

Penso che otterrete risposte più specifiche se è possibile pubblicare un campione specifico che mostri il problema. Ma in generale, penso che il punto di un modello di vista sia quello di * persistere * sui carichi di pagina, quindi non dovresti essere sorpreso che la vista della seconda pagina conservi i dati dalla prima vista. Puoi gestirlo spostando parte della pagina init dal costruttore in una funzione chiamata dal costruttore e anche dall'evento caricato pagina. – BobHy

+0

Questo è esattamente quello che ho fatto. Ma c'è un problema di memoria, dal momento che il viewmodel non viene cancellato durante la navigazione. E poiché il datacontext è impostato sulla vista, non riesco ad accedere al modello di visualizzazione. Quello che dovevo fare finora era impostare datacontext = null e chiamare GC.collect(). Ma questo non è un bel modo per farlo. Volevo sapere qual è il modo corretto. – JTIM

+1

Per favore pubblica un campione che mostri quello che stai facendo attualmente (con commenti che mostrano cosa vorresti che accadesse). Avere il modello di visualizzazione V1 per una data pagina P1 è ancora in memoria quando P1 viene caricato una seconda volta, questo è ciò che dovrebbe accadere. Stai vedendo qualche altro modello di visualizzazione in P1.DataContext? – BobHy

risposta

3

Le proprietà del ViewModelLocator restituiscono Singletons. Per rendere la proprietà restituire una nuova istanza ogni volta che si può semplicemente scrivere:

private int questCount; 

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

Tuttavia, il risultato sarà una domanda ViewModel caching. Devi rilasciare ViewModel inutilizzati seguendo attentamente la risposta che hai collegato. Ciò risulta nella mia opinione in troppi codice per un risultato semplice. Esistono altri contenitori IOC che è possibile utilizzare al posto di SimpleIoc su Windows Phone (come ninject o unity), che potrebbe essere più adatto alle proprie esigenze.

In un progetto semplice (un'applicazione paio-di-pagine), in particolare nel caso di non dover molta esperienza con il contenitore CIO, vi consiglio di abbandonare tutto ciò che il cablaggio SimpleIoc e basta chiamare il costruttore:

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

Grazie per la risposta, il mio progetto è piuttosto grande e sto usando tre modelli visivi. Ho provato a implementare la funzione di pulizia senza far funzionare il tutto perché non sapevo come chiamare la pulizia e come garantire che la pulizia fosse eseguita su tutte le variabili, anche se statiche. Posso fare il codice che ho collegato e farlo funzionare, ma non capisco come funziona la chiave. Quindi non mi piace molto usare il codice, non so come mantenere. Quindi mi piacerebbe usare SimpleIoc visto che sto usando MVVM light, ma non so come farlo. Aggiornerò la mia domanda con il mio Viewmodellocator. – JTIM

+0

@JTIM Tre ViewModels con costruttori molto semplici (a giudicare dall'impostazione SimpleIoc), sono * sicuramente * il caso in cui * non * utilizzerei un contenitore IOC. Le chiamate al costruttore esplicito produrranno molto meno codice che sicuramente capirai. – lisp

+0

@JTIM Per SimpleIoc - GetInstance restituisce la stessa istanza, GetInstance con la chiave data restituisce la stessa istanza per la chiave specificata. Annulla registrazione consente di eliminare un'istanza assegnata alla chiave. Questa è solo una specifica SimpleIoc. Ciò lo rende utile in alcuni scenari, in alcuni è difficile da applicare. SimpleIoc è solo uno degli helper in MVVMLight: non è necessario utilizzarli tutti in ogni progetto. ViewModelLocator può essere facilmente scritto senza di esso. – lisp

Problemi correlati