Передача параметра между ViewModels с использованием MVVMLight

У меня проблема с передачей параметров между моими ViewModels с использованием класса Messenger в MVVMLight Framework.

Это код, который я использую:

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

public SecondViewModel(INavigationService navigationService)
{
    _navigationService = navigationService;

    Messenger.Default.Register<Person>(
        this,
        person =>
        {
            Person = person;
        });
}

В моем MainViewModel (ShowPersonDetailsCommand), я перехожу на SecondPage и отправляю человека в качестве параметра в классе Messenger. На данный момент человек хорошо построен и отправлен в виде сообщения.

Но в SecondViewModel конструктор, человек ноль:(

Я что-то упускаю?

Я думаю, что сделал что-то не так...

Довожу до вашего сведения:

  • Windows Phone 8.1 (Silverlight)

  • MVVMLight 5.0.2

  • Visual Studio 2013, обновление 4

3 ответа

Решение

Я бы предложил создать SecondViewModel сразу же, как только он зарегистрирован в ViewModelLocator, Вы можете сделать это, используя перегруженный метод Register,

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

Это позволит убедиться, что Messenger регистрация происходит до отправки сообщения.

Когда вы отправили сообщение, SecondViewModel еще не был создан; он создается только при доступе к SecondViewModel собственность ViewModelLocator, Итак, ваше сообщение было отправлено, и ничем не обработано. Затем, когда SecondViewModel экземпляр создан, сообщение уже отправлено...

Я предлагаю вам отправить сообщение после звонка NavigateTo, это должно решить проблему.

Вместо отправки сообщения вы можете передать параметр в вызове метода NavigationServicesEx.Navigate.

В этом блоге Марко Минервы рассказывается, как подключиться к событию Frame_Navigating (которое отсутствует в классе vanilla NavigationServiceEx), чтобы получить доступ к аргументу при переходе на целевую страницу.

Создайте интерфейс INavigable, описанный в блоге:

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

Добавьте обработчик для события Frame.Navigating в классе NavigationServicesEx (с некоторыми дополнительными функциями, см. Блог), затем реализуйте интерфейс INavigable в ваших моделях ViewModels.

После этого вы сможете получить доступ к параметру, который вы передали в своем вызове Navigate:

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

В методе OnNavigatedToAsync, который вы реализуете в своей модели представления:

public Task OnNavigatedToAsync(object parameter, NavigationMode mode)
{
    if (parameter != null)
    {
        YourThing thing = parameter as YourThing;
        this.UseYourThing(thing);
    }
    return Task.CompletedTask;
}
Другие вопросы по тегам