5

Ho problemi a passare i parametri tra i miei ViewModels utilizzando la classe Messenger in MVVMLight Framework.Passare il parametro tra ViewModels utilizzando MVVMLight

Questo è il codice che sto utilizzando:

ViewModelLocator

public ViewModelLocator() 
{ 
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

    SimpleIoc.Default.Register<INavigationService, NavigationService>(); 

    SimpleIoc.Default.Register(() => new MainViewModel(NavigationService)); 
    SimpleIoc.Default.Register(() => new SecondViewModel(NavigationService)); 
} 

public MainViewModel MainViewModel 
{ 
    get { return SimpleIoc.Default.GetInstance<MainViewModel>(); } 
} 

public SecondViewModel SecondViewModel 
{ 
    get { return SimpleIoc.Default.GetInstance<SecondViewModel>(); } 
} 

public INavigationService NavigationService 
{ 
    get { return SimpleIoc.Default.GetInstance<INavigationService>(); } 
} 

MainViewModel

private void ShowPersonDetailsCommand(object obj) 
{ 
    Messenger.Default.Send((Person)obj); 
    _navigationService.NavigateTo(new Uri("/SecondPage.xaml", UriKind.Relative)) 
} 

SecondViewModel

Nel mio MainViewModel (ShowPersonDetailsCommand), sto navigando su una seconda pagina e invio una persona come parametro nella classe Messenger. A questo punto, la persona è ben costruita e inviata come messaggio.

Ma nel costruttore SecondViewModel, la persona è nulla :(

C'è qualcosa che mi manca

I pensa che ho fatto qualcosa di sbagliato ...

Per vostra informazione?:

  • Windows Phone 8.1 (Silverlight)

  • MVVMLight 5.0.2

  • Visual Studio 2013 Aggiornamento 4

risposta

8

Suggerirei di creare immediatamente lo SecondViewModel non appena viene registrato nel ViewModelLocator. È possibile farlo utilizzando un metodo sovraccarico di Register.

SimpleIoc.Default.Register<SecondViewModel>(true); 

Questo farà in modo che in modo che la registrazione Messenger avviene prima che il messaggio viene inviato.

+0

Questo ha funzionato per me, grazie :) –

1

al momento dell'invio del messaggio, il SecondViewModel non era ancora creata; viene creato solo quando si accede alla proprietà SecondViewModel di ViewModelLocator. Quindi il tuo messaggio è stato inviato e non è stato gestito da nulla. Quindi, quando è stata creata l'istanza SecondViewModel, il messaggio era già stato inviato ...

Suggerisco di inviare il messaggio dopo la chiamata a NavigateTo, dovrebbe risolvere il problema.

+0

l'ho fatto, ma non cambia nulla :( –

+0

@Christophe, come viene implementato il tuo NavigationService? Il metodo NavigateTo può accettare un argomento per passare alla pagina di destinazione? Se possibile, è probabilmente un modo migliore per passare i dati tra ViewModels ... –

+0

My NavigationService ca n prendere uno stato (oggetto) come argomento. Ma il problema è che non voglio ottenere quell'argomento nel codice sottostante. Perché AFAIK possiamo ottenere quello stato solo quando sostituiamo OnNavigatedTo! –

0

Invece di inviare un messaggio, è possibile passare un parametro nella chiamata al metodo NavigationServicesEx.Navigate.

Questo blog di Marco Minerva consiglia come eseguire il collegamento all'evento Frame_Navigating (che manca dalla classe vanail NavigationServiceEx) per accedere all'argomento quando si naviga sulla pagina di destinazione.

Creare l'interfaccia INavigable descritto nel blog:

public interface INavigable 
{ 
    Task OnNavigatedToAsync(object parameter, NavigationMode mode); 
    void OnNavigatingFrom(NavigatingCancelEventArgs e); 
    void OnNavigatedFrom(); 
} 

aggiungere un gestore per l'evento Frame.Navigating nella classe NavigationServicesEx (con qualche impianto idraulico supplementare, vedi blog) poi rendersi conto l'interfaccia INavigable nei tuoi ViewModels .

Sarete quindi in grado di accedere al parametro che avete passato nella vostra chiamata Naviga:

NavigationServiceEx.Navigate(typeof(DestinationPage).FullName, yourParameter); 

Nel metodo OnNavigatedToAsync implementare nel vostro ViewModel:

public Task OnNavigatedToAsync(object parameter, NavigationMode mode) 
{ 
    if (parameter != null) 
    { 
     YourThing thing = parameter as YourThing; 
     this.UseYourThing(thing); 
    } 
    return Task.CompletedTask; 
}